Skip to content
This repository was archived by the owner on Sep 16, 2024. It is now read-only.

Commit a5aa0b8

Browse files
authored
Merge pull request #479 from pycom/prep_v1.20.2.r1
Prep v1.20.2.r1
2 parents 24c3576 + 539ff1e commit a5aa0b8

6 files changed

+223
-26
lines changed

esp32/frozen/Pybytes/_pybytes_constants.py

+10-3
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,12 @@ class constants:
6969
__TYPE_OTA = 0x05
7070
__TYPE_FCOTA = 0x06
7171
__TYPE_PONG = 0x07
72-
__TYPE_PYMESH = 0x0D
73-
__TYPE_PYBYTES = 0x0E
74-
__TYPE_RELEASE_INFO = 0x0B
7572
__TYPE_RELEASE_DEPLOY = 0x0A
73+
__TYPE_RELEASE_INFO = 0x0B
7674
__TYPE_DEVICE_NETWORK_DEPLOY = 0x0C
75+
__TYPE_PYMESH = 0x0D
76+
__TYPE_PYBYTES = 0x0E
77+
__TYPE_ML = 0x0F
7778
__PYBYTES_PROTOCOL = ">B%ds"
7879
__PYBYTES_PROTOCOL_PING = ">B"
7980
__PYBYTES_INTERNAL_PROTOCOL = ">BBH"
@@ -90,6 +91,8 @@ class constants:
9091
__COMMAND_ANALOG_WRITE = 4
9192
__COMMAND_CUSTOM_METHOD = 5
9293
__COMMAND_CUSTOM_LOCATION = 6
94+
__COMMAND_START_SAMPLE = 7
95+
__COMMAND_DEPLOY_MODEL = 8
9396

9497
__FCOTA_COMMAND_HIERARCHY_ACQUISITION = 0x00
9598
__FCOTA_COMMAND_FILE_ACQUISITION = 0x01
@@ -105,6 +108,10 @@ class constants:
105108
__DEVICE_TYPE_LOPY_4 = 0x04
106109
__DEVICE_TYPE_UNKNOWN = 0x05
107110

111+
__FWTYPE_DEFAULT = 0x00
112+
__FWTYPE_PYMESH = 0x01
113+
__FWTYPE_PYGATE = 0x02
114+
108115
# {"ssid":"%s", "mac_addr":"%s", "channel":"%s", "power":"%s"}
109116
__WIFI_NETWORK_FORMAT = ">6sBb"
110117

esp32/frozen/Pybytes/_pybytes_library.py

+12-3
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,18 @@ def pack_info_message(self, releaseVersion=None):
8686
body.append((release >> 8) & 0xFF)
8787
body.append(release & 0xFF)
8888

89-
if releaseVersion is not None:
90-
body.append((releaseVersion >> 8) & 0xFF)
91-
body.append(releaseVersion & 0xFF)
89+
if releaseVersion is None:
90+
releaseVersion = 0
91+
92+
body.append((releaseVersion >> 8) & 0xFF)
93+
body.append(releaseVersion & 0xFF)
94+
95+
if hasattr(os.uname(), 'pymesh'):
96+
body.append(constants.__FWTYPE_PYMESH)
97+
elif hasattr(os.uname(), 'pygate'):
98+
body.append(constants.__FWTYPE_PYGATE)
99+
else:
100+
body.append(constants.__FWTYPE_DEFAULT)
92101

93102
return self.__pack_message(constants.__TYPE_INFO, body)
94103

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
'''
2+
Copyright (c) 2020, Pycom Limited.
3+
This software is licensed under the GNU GPL version 3 or any
4+
later version, with permitted additional terms. For more information
5+
see the Pycom Licence v1.0 document supplied with this file, or
6+
available at https://www.pycom.io/opensource/licensing
7+
'''
8+
9+
import math
10+
import json
11+
12+
try:
13+
from pybytes_debug import print_debug
14+
except:
15+
from _pybytes_debug import print_debug
16+
17+
try:
18+
import urequest
19+
except:
20+
import _urequest as urequest
21+
22+
try:
23+
from pybytes_constants import constants
24+
except:
25+
from _pybytes_constants import constants
26+
27+
import pycom
28+
29+
try:
30+
from LIS2HH12 import *
31+
except:
32+
print_debug(5, "LIS2HH12 not imported")
33+
34+
# 20 seconds, max window in time for recording
35+
MAX_LEN_MSEC = const(20000)
36+
37+
# 350Hz, max frequency
38+
MAX_FREQ_HZ = const(350)
39+
40+
41+
class MlFeatures():
42+
def __init__(self, pybytes_protocol=None, parameters=None):
43+
if parameters is not None:
44+
self.__length = parameters["length"]
45+
self.__label = parameters["label"]
46+
self.__sampleName = parameters["sampleName"]
47+
self.__type = parameters["type"]
48+
self.__device = parameters["device"]
49+
self.__model = parameters["model"]
50+
self.__mlSample = parameters["mlSample"]
51+
self.__frequency = parameters["frequency"]
52+
self.__pybytes_protocol = pybytes_protocol
53+
self.__data = []
54+
55+
def _debug_hack(self, pybytes):
56+
self.__pybytes = pybytes
57+
58+
def start_sampling(self, pin):
59+
# here define the required libraries
60+
try:
61+
from pysense import Pysense
62+
except:
63+
print_debug(5, "pysense not imported")
64+
65+
try:
66+
from pytrack import Pytrack
67+
except:
68+
print_debug(5, "pytrack not imported")
69+
70+
lib = False
71+
try:
72+
py = Pysense()
73+
lib = True
74+
except NameError:
75+
print_debug(5, "Pysense not defined")
76+
77+
if not lib:
78+
try:
79+
py = Pytrack()
80+
except NameError:
81+
print_debug(5, "Check if Pysense/Pytrack libraries are loaded")
82+
return
83+
84+
try:
85+
li = LIS2HH12(py)
86+
except NameError:
87+
print_debug(5, "LIS2HH12 library are not loaded")
88+
return
89+
li.set_odr(ODR_400_HZ)
90+
91+
# make the max record length to 20 seconds
92+
self.__length = min(MAX_LEN_MSEC, self.__length)
93+
94+
# make the max frequency to 350Hz
95+
self.__frequency = min(MAX_FREQ_HZ, self.__frequency)
96+
97+
# compute time interval between 2 consecutive samples
98+
delta_t_us = int(1000000.0 / self.__frequency)
99+
# compute the number of samples to be acquisition
100+
samples_num = math.ceil(self.__length * self.__frequency / 1000) + 1
101+
102+
pycom.heartbeat(False)
103+
pycom.rgbled(0x7f7f00)
104+
time.sleep(0.5)
105+
106+
self.__data = []
107+
index = 0
108+
print("Start acquisition data for %d msec, freq %d Hz" % (self.__length, self.__frequency))
109+
110+
next_ts = time.ticks_us()
111+
ts_orig = next_ts
112+
while True:
113+
while time.ticks_diff(next_ts, time.ticks_us()) > 0:
114+
pass
115+
acc = li.acceleration()
116+
ts = next_ts
117+
self.__data.append((ts - ts_orig, acc))
118+
next_ts = ts + delta_t_us
119+
index += 1
120+
if index >= samples_num:
121+
break # done
122+
123+
print("Done acquisition %d samples, real freq %.1f Hz" % (index, index / (self.__length / 1000)))
124+
self._parse_data(pin)
125+
126+
def _send_data(self, data, pin, acc, ts):
127+
if self.__pybytes_protocol is not None:
128+
if self.__type == 2:
129+
self.__label = self.__sampleName
130+
self.__pybytes_protocol.send_pybytes_custom_method_values(pin, [
131+
data],
132+
'sample/{}/{}/{}/{}/{}'.format(self.__label, self.__type, self.__model, self.__device, self.__mlSample))
133+
else:
134+
self.__pybytes.send_signal(pin & 0xFF, str((int(ts / 1000), acc)))
135+
136+
def _parse_data(self, pin):
137+
print("_parse_data, %d samples" % len(self.__data))
138+
pycom.rgbled(0x8d05f5)
139+
data = ['{"data": "ml"}']
140+
for (ts, acc) in self.__data:
141+
data.append('{' + '"data": [{},{},{}], "ms": {}'.format(acc[0], acc[1], acc[2], int(ts / 1000)) + '}')
142+
if len(data) > 25:
143+
self._send_data(data, pin, acc, ts)
144+
data = ['{"data": "ml"}']
145+
self._send_data(data, pin, acc, ts)
146+
pycom.heartbeat(True)
147+
148+
def deploy_model(self, modelId, silent=False):
149+
try:
150+
file = '/flash/model_definition.json'
151+
modelDefinition = {}
152+
url = '{}://{}/ml/{}'.format(
153+
constants.__DEFAULT_PYCONFIG_PROTOCOL,
154+
constants.__DEFAULT_PYCONFIG_DOMAIN,
155+
modelId
156+
)
157+
print_debug(2, '{}'.format(url))
158+
result = urequest.get(url, headers={'content-type': 'application/json'})
159+
modelDefinition = json.loads(result.content.decode())
160+
print_debug(2, 'modelDefinition: {}'.format(modelDefinition))
161+
f = open(file, 'w')
162+
f.write(json.dumps(modelDefinition).encode('utf-8'))
163+
f.close()
164+
print_debug(2, "Model definition written to {}".format(file))
165+
except Exception as e:
166+
if not silent:
167+
print_debug(2, "Exception: {}".format(e))

esp32/frozen/Pybytes/_pybytes_protocol.py

+20-4
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@
3131
except:
3232
from _pybytes_pymesh_config import PybytesPymeshConfig
3333

34+
try:
35+
from pybytes_machine_learning import MlFeatures
36+
except:
37+
from _pybytes_machine_learning import MlFeatures
38+
3439
try:
3540
from pybytes_config_reader import PybytesConfigReader
3641
except:
@@ -281,10 +286,10 @@ def __process_recv_message(self, message):
281286
splittedBody = bodyString.split(',')
282287
if (len(splittedBody) >= 2):
283288
path = splittedBody[0]
284-
print_debug(2, path[len(path)-7:len(path)])
285-
if (path[len(path)-7:len(path)] != '.pymakr'):
289+
print_debug(2, path[len(path) - 7:len(path)])
290+
if (path[len(path) - 7:len(path)] != '.pymakr'):
286291
self.send_fcota_ping('updating file...')
287-
newContent = bodyString[len(path)+1:len(body)]
292+
newContent = bodyString[len(path) + 1:len(body)]
288293
if (self.__FCOTA.update_file_content(path, newContent) is True): # noqa
289294
size = self.__FCOTA.get_file_size(path)
290295
self.send_fcota_file(newContent, path, size)
@@ -319,7 +324,18 @@ def __process_recv_message(self, message):
319324
if (len(body) > 3):
320325
value = body[2] << 8 | body[3]
321326

322-
if (command == constants.__COMMAND_PIN_MODE):
327+
if (command == constants.__COMMAND_START_SAMPLE):
328+
parameters = ujson.loads(body[2: len(body)].decode("utf-8"))
329+
sampling = MlFeatures(self, parameters=parameters)
330+
sampling.start_sampling(pin=parameters["pin"])
331+
self.send_ota_response(result=2, topic='sample')
332+
elif (command == constants.__COMMAND_DEPLOY_MODEL):
333+
parameters = ujson.loads(body[2: len(body)].decode("utf-8"))
334+
sampling = MlFeatures()
335+
sampling.deploy_model(modelId=parameters["modelId"])
336+
self.send_ota_response(result=2, topic='deploymlmodel')
337+
338+
elif (command == constants.__COMMAND_PIN_MODE):
323339
pass
324340

325341
elif (command == constants.__COMMAND_DIGITAL_READ):

esp32/frozen/Pybytes/_pybytes_pymesh_config.py

+12-14
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,6 @@ def pymesh_init(self):
5353
# initialize Pymesh
5454
self.__pymesh = Pymesh(self.__pymesh_config, self.pymesh_new_message_cb)
5555

56-
while not self.__pymesh.is_connected():
57-
print(self.__pymesh.status_str())
58-
time.sleep(3)
59-
60-
# send message to the Node having MAC address 5
61-
self.__pymesh.send_mess(2, "Hello World")
62-
print("Done Pymesh init, forever loop, exit/stop with Ctrl+C multiple times")
6356
self.__pymesh_br_enabled = False
6457

6558
if self.__pymesh_config.get("br_ena", False):
@@ -69,8 +62,6 @@ def pymesh_init(self):
6962
print_debug(99, "Set as border router")
7063
self.__pymesh.br_set(PymeshConfig.BR_PRIORITY_NORM, self.pymesh_new_br_message_cb)
7164

72-
self.__pybytes.send_signal(1, str(self.__pymesh.mac()) + " : " + str(time.time()) + "s, " + str(pycom.get_free_heap()))
73-
print_debug(99, "Send to Pyb,", pycom.get_free_heap())
7465
else: # not connected anymore to pybytes
7566
if self.__pymesh_br_enabled:
7667
self.__pymesh_br_enabled = False
@@ -88,8 +79,13 @@ def unpack_pymesh_message(self, signal_number, value):
8879
pyb_ip = '1:2:3::' + hex(pyb_port)[2:]
8980
pkt_start = self.__pack_tocken_prefix + self.__pack_tocken_sep + deviceID + self.__pack_tocken_sep
9081

91-
self.__pymesh.send_mess_external(pyb_ip, pyb_port, pkt_start + monitoringData)
92-
self.__pymesh.send_mess_external(pyb_ip, pyb_port, pkt_start + value)
82+
# send data to the port equal with signal_number
83+
self.__pymesh.send_mess_external(pyb_ip, signal_number, pkt_start + value)
84+
85+
time.sleep(3) # shouldn't send too fast to BR
86+
87+
# hardcode monitoring data to be sent on signal #2
88+
self.__pymesh.send_mess_external(pyb_ip, 2, pkt_start + monitoringData)
9389

9490
def pymesh_new_message_cb(self, rcv_ip, rcv_port, rcv_data):
9591
''' callback triggered when a new packet arrived '''
@@ -122,9 +118,11 @@ def pymesh_new_br_message_cb(self, rcv_ip, rcv_port, rcv_data, dest_ip, dest_por
122118
if len(x) > 2:
123119
token = x[1]
124120
rcv_data = rcv_data[len(self.__pack_tocken_prefix) + len(token) + len(self.__pack_tocken_sep):]
125-
pkt = 'BR %d B from %s (%s), to %s ( %d): %s' % (len(rcv_data), token, rcv_ip, dest_ip, dest_port, str(rcv_data))
126-
print_debug(99, 'Pymesh node packet: {} '.format(pkt))
127-
self.__pybytes.send_node_signal(1, str(rcv_data.decode()).replace("#", ""), token.decode())
121+
122+
# send data to Pybytes only if it's coded properly
123+
pkt = 'BR %d B from %s (%s), to %s ( %d): %s' % (len(rcv_data), token, rcv_ip, dest_ip, dest_port, str(rcv_data))
124+
print_debug(99, 'Pymesh node packet: {} '.format(pkt))
125+
self.__pybytes.send_node_signal(dest_port & 0xFF, str(rcv_data.decode()).replace("#", ""), token.decode())
128126
return
129127

130128
def get_config(self, token, silent=False):

esp32/pycom_version.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@
1010
#ifndef VERSION_H_
1111
#define VERSION_H_
1212

13-
#define SW_VERSION_NUMBER "1.20.2.r0"
13+
#define SW_VERSION_NUMBER "1.20.2.r1"
1414

1515
#define LORAWAN_VERSION_NUMBER "1.0.2"
1616

1717
#define SIGFOX_VERSION_NUMBER "1.0.1"
1818

1919
#if (VARIANT == PYBYTES)
20-
#define PYBYTES_VERSION_NUMBER "1.5.1"
20+
#define PYBYTES_VERSION_NUMBER "1.6.0"
2121
#endif
2222

2323
#endif /* VERSION_H_ */

0 commit comments

Comments
 (0)