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

Prep v1.20.2.r1 #479

Merged
merged 2 commits into from
Sep 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions esp32/frozen/Pybytes/_pybytes_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,12 @@ class constants:
__TYPE_OTA = 0x05
__TYPE_FCOTA = 0x06
__TYPE_PONG = 0x07
__TYPE_PYMESH = 0x0D
__TYPE_PYBYTES = 0x0E
__TYPE_RELEASE_INFO = 0x0B
__TYPE_RELEASE_DEPLOY = 0x0A
__TYPE_RELEASE_INFO = 0x0B
__TYPE_DEVICE_NETWORK_DEPLOY = 0x0C
__TYPE_PYMESH = 0x0D
__TYPE_PYBYTES = 0x0E
__TYPE_ML = 0x0F
__PYBYTES_PROTOCOL = ">B%ds"
__PYBYTES_PROTOCOL_PING = ">B"
__PYBYTES_INTERNAL_PROTOCOL = ">BBH"
Expand All @@ -90,6 +91,8 @@ class constants:
__COMMAND_ANALOG_WRITE = 4
__COMMAND_CUSTOM_METHOD = 5
__COMMAND_CUSTOM_LOCATION = 6
__COMMAND_START_SAMPLE = 7
__COMMAND_DEPLOY_MODEL = 8

__FCOTA_COMMAND_HIERARCHY_ACQUISITION = 0x00
__FCOTA_COMMAND_FILE_ACQUISITION = 0x01
Expand All @@ -105,6 +108,10 @@ class constants:
__DEVICE_TYPE_LOPY_4 = 0x04
__DEVICE_TYPE_UNKNOWN = 0x05

__FWTYPE_DEFAULT = 0x00
__FWTYPE_PYMESH = 0x01
__FWTYPE_PYGATE = 0x02

# {"ssid":"%s", "mac_addr":"%s", "channel":"%s", "power":"%s"}
__WIFI_NETWORK_FORMAT = ">6sBb"

Expand Down
15 changes: 12 additions & 3 deletions esp32/frozen/Pybytes/_pybytes_library.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,18 @@ def pack_info_message(self, releaseVersion=None):
body.append((release >> 8) & 0xFF)
body.append(release & 0xFF)

if releaseVersion is not None:
body.append((releaseVersion >> 8) & 0xFF)
body.append(releaseVersion & 0xFF)
if releaseVersion is None:
releaseVersion = 0

body.append((releaseVersion >> 8) & 0xFF)
body.append(releaseVersion & 0xFF)

if hasattr(os.uname(), 'pymesh'):
body.append(constants.__FWTYPE_PYMESH)
elif hasattr(os.uname(), 'pygate'):
body.append(constants.__FWTYPE_PYGATE)
else:
body.append(constants.__FWTYPE_DEFAULT)

return self.__pack_message(constants.__TYPE_INFO, body)

Expand Down
167 changes: 167 additions & 0 deletions esp32/frozen/Pybytes/_pybytes_machine_learning.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
'''
Copyright (c) 2020, Pycom Limited.
This software is licensed under the GNU GPL version 3 or any
later version, with permitted additional terms. For more information
see the Pycom Licence v1.0 document supplied with this file, or
available at https://www.pycom.io/opensource/licensing
'''

import math
import json

try:
from pybytes_debug import print_debug
except:
from _pybytes_debug import print_debug

try:
import urequest
except:
import _urequest as urequest

try:
from pybytes_constants import constants
except:
from _pybytes_constants import constants

import pycom

try:
from LIS2HH12 import *
except:
print_debug(5, "LIS2HH12 not imported")

# 20 seconds, max window in time for recording
MAX_LEN_MSEC = const(20000)

# 350Hz, max frequency
MAX_FREQ_HZ = const(350)


class MlFeatures():
def __init__(self, pybytes_protocol=None, parameters=None):
if parameters is not None:
self.__length = parameters["length"]
self.__label = parameters["label"]
self.__sampleName = parameters["sampleName"]
self.__type = parameters["type"]
self.__device = parameters["device"]
self.__model = parameters["model"]
self.__mlSample = parameters["mlSample"]
self.__frequency = parameters["frequency"]
self.__pybytes_protocol = pybytes_protocol
self.__data = []

def _debug_hack(self, pybytes):
self.__pybytes = pybytes

def start_sampling(self, pin):
# here define the required libraries
try:
from pysense import Pysense
except:
print_debug(5, "pysense not imported")

try:
from pytrack import Pytrack
except:
print_debug(5, "pytrack not imported")

lib = False
try:
py = Pysense()
lib = True
except NameError:
print_debug(5, "Pysense not defined")

if not lib:
try:
py = Pytrack()
except NameError:
print_debug(5, "Check if Pysense/Pytrack libraries are loaded")
return

try:
li = LIS2HH12(py)
except NameError:
print_debug(5, "LIS2HH12 library are not loaded")
return
li.set_odr(ODR_400_HZ)

# make the max record length to 20 seconds
self.__length = min(MAX_LEN_MSEC, self.__length)

# make the max frequency to 350Hz
self.__frequency = min(MAX_FREQ_HZ, self.__frequency)

# compute time interval between 2 consecutive samples
delta_t_us = int(1000000.0 / self.__frequency)
# compute the number of samples to be acquisition
samples_num = math.ceil(self.__length * self.__frequency / 1000) + 1

pycom.heartbeat(False)
pycom.rgbled(0x7f7f00)
time.sleep(0.5)

self.__data = []
index = 0
print("Start acquisition data for %d msec, freq %d Hz" % (self.__length, self.__frequency))

next_ts = time.ticks_us()
ts_orig = next_ts
while True:
while time.ticks_diff(next_ts, time.ticks_us()) > 0:
pass
acc = li.acceleration()
ts = next_ts
self.__data.append((ts - ts_orig, acc))
next_ts = ts + delta_t_us
index += 1
if index >= samples_num:
break # done

print("Done acquisition %d samples, real freq %.1f Hz" % (index, index / (self.__length / 1000)))
self._parse_data(pin)

def _send_data(self, data, pin, acc, ts):
if self.__pybytes_protocol is not None:
if self.__type == 2:
self.__label = self.__sampleName
self.__pybytes_protocol.send_pybytes_custom_method_values(pin, [
data],
'sample/{}/{}/{}/{}/{}'.format(self.__label, self.__type, self.__model, self.__device, self.__mlSample))
else:
self.__pybytes.send_signal(pin & 0xFF, str((int(ts / 1000), acc)))

def _parse_data(self, pin):
print("_parse_data, %d samples" % len(self.__data))
pycom.rgbled(0x8d05f5)
data = ['{"data": "ml"}']
for (ts, acc) in self.__data:
data.append('{' + '"data": [{},{},{}], "ms": {}'.format(acc[0], acc[1], acc[2], int(ts / 1000)) + '}')
if len(data) > 25:
self._send_data(data, pin, acc, ts)
data = ['{"data": "ml"}']
self._send_data(data, pin, acc, ts)
pycom.heartbeat(True)

def deploy_model(self, modelId, silent=False):
try:
file = '/flash/model_definition.json'
modelDefinition = {}
url = '{}://{}/ml/{}'.format(
constants.__DEFAULT_PYCONFIG_PROTOCOL,
constants.__DEFAULT_PYCONFIG_DOMAIN,
modelId
)
print_debug(2, '{}'.format(url))
result = urequest.get(url, headers={'content-type': 'application/json'})
modelDefinition = json.loads(result.content.decode())
print_debug(2, 'modelDefinition: {}'.format(modelDefinition))
f = open(file, 'w')
f.write(json.dumps(modelDefinition).encode('utf-8'))
f.close()
print_debug(2, "Model definition written to {}".format(file))
except Exception as e:
if not silent:
print_debug(2, "Exception: {}".format(e))
24 changes: 20 additions & 4 deletions esp32/frozen/Pybytes/_pybytes_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@
except:
from _pybytes_pymesh_config import PybytesPymeshConfig

try:
from pybytes_machine_learning import MlFeatures
except:
from _pybytes_machine_learning import MlFeatures

try:
from pybytes_config_reader import PybytesConfigReader
except:
Expand Down Expand Up @@ -281,10 +286,10 @@ def __process_recv_message(self, message):
splittedBody = bodyString.split(',')
if (len(splittedBody) >= 2):
path = splittedBody[0]
print_debug(2, path[len(path)-7:len(path)])
if (path[len(path)-7:len(path)] != '.pymakr'):
print_debug(2, path[len(path) - 7:len(path)])
if (path[len(path) - 7:len(path)] != '.pymakr'):
self.send_fcota_ping('updating file...')
newContent = bodyString[len(path)+1:len(body)]
newContent = bodyString[len(path) + 1:len(body)]
if (self.__FCOTA.update_file_content(path, newContent) is True): # noqa
size = self.__FCOTA.get_file_size(path)
self.send_fcota_file(newContent, path, size)
Expand Down Expand Up @@ -319,7 +324,18 @@ def __process_recv_message(self, message):
if (len(body) > 3):
value = body[2] << 8 | body[3]

if (command == constants.__COMMAND_PIN_MODE):
if (command == constants.__COMMAND_START_SAMPLE):
parameters = ujson.loads(body[2: len(body)].decode("utf-8"))
sampling = MlFeatures(self, parameters=parameters)
sampling.start_sampling(pin=parameters["pin"])
self.send_ota_response(result=2, topic='sample')
elif (command == constants.__COMMAND_DEPLOY_MODEL):
parameters = ujson.loads(body[2: len(body)].decode("utf-8"))
sampling = MlFeatures()
sampling.deploy_model(modelId=parameters["modelId"])
self.send_ota_response(result=2, topic='deploymlmodel')

elif (command == constants.__COMMAND_PIN_MODE):
pass

elif (command == constants.__COMMAND_DIGITAL_READ):
Expand Down
26 changes: 12 additions & 14 deletions esp32/frozen/Pybytes/_pybytes_pymesh_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,6 @@ def pymesh_init(self):
# initialize Pymesh
self.__pymesh = Pymesh(self.__pymesh_config, self.pymesh_new_message_cb)

while not self.__pymesh.is_connected():
print(self.__pymesh.status_str())
time.sleep(3)

# send message to the Node having MAC address 5
self.__pymesh.send_mess(2, "Hello World")
print("Done Pymesh init, forever loop, exit/stop with Ctrl+C multiple times")
self.__pymesh_br_enabled = False

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

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

self.__pymesh.send_mess_external(pyb_ip, pyb_port, pkt_start + monitoringData)
self.__pymesh.send_mess_external(pyb_ip, pyb_port, pkt_start + value)
# send data to the port equal with signal_number
self.__pymesh.send_mess_external(pyb_ip, signal_number, pkt_start + value)

time.sleep(3) # shouldn't send too fast to BR

# hardcode monitoring data to be sent on signal #2
self.__pymesh.send_mess_external(pyb_ip, 2, pkt_start + monitoringData)

def pymesh_new_message_cb(self, rcv_ip, rcv_port, rcv_data):
''' callback triggered when a new packet arrived '''
Expand Down Expand Up @@ -122,9 +118,11 @@ def pymesh_new_br_message_cb(self, rcv_ip, rcv_port, rcv_data, dest_ip, dest_por
if len(x) > 2:
token = x[1]
rcv_data = rcv_data[len(self.__pack_tocken_prefix) + len(token) + len(self.__pack_tocken_sep):]
pkt = 'BR %d B from %s (%s), to %s ( %d): %s' % (len(rcv_data), token, rcv_ip, dest_ip, dest_port, str(rcv_data))
print_debug(99, 'Pymesh node packet: {} '.format(pkt))
self.__pybytes.send_node_signal(1, str(rcv_data.decode()).replace("#", ""), token.decode())

# send data to Pybytes only if it's coded properly
pkt = 'BR %d B from %s (%s), to %s ( %d): %s' % (len(rcv_data), token, rcv_ip, dest_ip, dest_port, str(rcv_data))
print_debug(99, 'Pymesh node packet: {} '.format(pkt))
self.__pybytes.send_node_signal(dest_port & 0xFF, str(rcv_data.decode()).replace("#", ""), token.decode())
return

def get_config(self, token, silent=False):
Expand Down
4 changes: 2 additions & 2 deletions esp32/pycom_version.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
#ifndef VERSION_H_
#define VERSION_H_

#define SW_VERSION_NUMBER "1.20.2.r0"
#define SW_VERSION_NUMBER "1.20.2.r1"

#define LORAWAN_VERSION_NUMBER "1.0.2"

#define SIGFOX_VERSION_NUMBER "1.0.1"

#if (VARIANT == PYBYTES)
#define PYBYTES_VERSION_NUMBER "1.5.1"
#define PYBYTES_VERSION_NUMBER "1.6.0"
#endif

#endif /* VERSION_H_ */