Skip to content
This repository has been archived by the owner on May 25, 2024. It is now read-only.

Commit

Permalink
add port_wifi_indoor_positioning
Browse files Browse the repository at this point in the history
  • Loading branch information
agrimagsrl committed Aug 9, 2020
1 parent 06e75d4 commit f7c57c9
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 4 deletions.
2 changes: 1 addition & 1 deletion MANIFEST
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ micromlgen/decisiontree.py
micromlgen/gaussiannb.py
micromlgen/logisticregression.py
micromlgen/micromlgen.py
micromlgen/patches.py
micromlgen/pca.py
micromlgen/platforms.py
micromlgen/randomforest.py
micromlgen/rvm.py
micromlgen/sefr.py
micromlgen/svm.py
micromlgen/utils.py
micromlgen/templates/_skeleton.jinja
micromlgen/templates/classmap.jinja
micromlgen/templates/dot.jinja
micromlgen/templates/testset.jinja
Expand Down
1 change: 1 addition & 0 deletions micromlgen/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import micromlgen.platforms as platforms
from micromlgen.micromlgen import port
from micromlgen.utils import port_testset, port_trainset
from micromlgen.wifiindoorpositioning import port_wifi_indoor_positioning
2 changes: 1 addition & 1 deletion micromlgen/micromlgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ def port(
return port_gaussiannb(**locals())
elif is_pca(clf):
return port_pca(**locals())
raise TypeError('clf MUST be one of SVC, LinearSVC, OneClassSVC, RVC, DecisionTree, RandomForest, LogisticRegression, GaussianNB, SEFR, PCA')
raise TypeError('clf MUST be one of %s' % ', '.join(platforms.ALLOWED_CLASSIFIERS))
13 changes: 13 additions & 0 deletions micromlgen/platforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,17 @@
ALL = [
ARDUINO,
ATTINY
]

ALLOWED_CLASSIFIERS = [
'SVC',
'LinearSVC',
'OneClassSVC',
'RVC',
'SEFR',
'DecisionTree',
'RandomForest',
'GaussianNB',
'LogisticRegression',
'PCA'
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#pragma once

namespace Eloquent {
namespace Projects {
class WifiIndoorPositioning {
public:
/**
* Get feature vector
*/
float* getFeatures() {
static float features[{{ X[0]|length }}] = {0};
uint8_t numNetworks = WiFi.scanNetworks();

for (uint8_t i = 0; i < {{ X[0]|length }}; i++) {
features[i] = 0;
}

for (uint8_t i = 0; i < numNetworks; i++) {
int featureIdx = ssidToFeatureIdx(WiFi.SSID(i));

if (featureIdx >= 0) {
features[featureIdx] = WiFi.RSSI(i);
}
}

return features;
}

protected:
/**
* Convert SSID to featureIdx
*/
int ssidToFeatureIdx(String ssid) {
{% for network, idx in networkmap.items() %}
if (ssid.equals("{{ network }}"))
return {{ idx }};
{% endfor %}

return -1;
}
};
}
}
69 changes: 69 additions & 0 deletions micromlgen/wifiindoorpositioning.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import json
import numpy as np
from micromlgen.utils import jinja


def parse_samples(samples, parser):
for line in samples.split('\n'):
if '{' in line and '}' in line:
data = json.loads(line)
info = {k: v for k, v in data.items() if k.startswith('__')}
networks = {k: v for k, v in data.items() if not k.startswith('__')}
yield parser(info, networks)


def get_classmap(samples):
"""Get {location: classIdx} mapping"""

def parser(info, networks):
return info['__location']

locations = list(parse_samples(samples, parser))
return {location: i for i, location in enumerate(sorted(set(locations)))}


def get_networkmap(samples):
"""Get {network: featureIdx} mapping"""

def parser(info, networks):
return networks.keys()

networks = [list(x) for x in parse_samples(samples, parser)]
networks = [network for sub in networks for network in sub]
return {network: i for i, network in enumerate(sorted(set(networks)))}


def get_x(samples, networkmap):
"""Get features array"""

def parser(info, networks):
x = [0] * len(networkmap)
for network, rssi in networks.items():
x[networkmap.get(network)] = rssi
return x

return np.asarray(list(parse_samples(samples, parser)), dtype=np.int8)


def get_y(samples, classmap):
"""Get locationIdx array"""

def parser(info, networks):
location = info['__location']
assert location in classmap, 'Unknown location %s' % location
return classmap[location]

return np.asarray(list(parse_samples(samples, parser)))


def port_wifi_indoor_positioning(samples):
classmap = get_classmap(samples)
networkmap = get_networkmap(samples)
X = get_x(samples, networkmap)
y = get_y(samples, classmap)
# classmap is flipped wrt the format `port` expects: flip it
classmap = {v: k for k, v in classmap.items()}
return X, y, classmap, jinja('wifiindoorpositioning/wifiindoorpositioning.jinja', {
'X': X,
'networkmap': networkmap
})
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
setup(
name = 'micromlgen',
packages = ['micromlgen'],
version = '1.1.7',
version = '1.1.8',
license='MIT',
description = 'Generate C code for microcontrollers from Python\'s sklearn classifiers',
author = 'Simone Salerno',
author_email = '[email protected]',
url = 'https://github.com/eloquentarduino/micromlgen',
download_url = 'https://github.com/eloquentarduino/micromlgen/archive/v_117.tar.gz',
download_url = 'https://github.com/eloquentarduino/micromlgen/archive/v_118.tar.gz',
keywords = [
'ML',
'microcontrollers',
Expand Down

0 comments on commit f7c57c9

Please sign in to comment.