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

Commit

Permalink
Merge pull request #479 from pycom/prep_v1.20.2.r1
Browse files Browse the repository at this point in the history
Prep v1.20.2.r1
  • Loading branch information
peter-pycom authored Sep 9, 2020
2 parents 24c3576 + 539ff1e commit a5aa0b8
Show file tree
Hide file tree
Showing 6 changed files with 223 additions and 26 deletions.
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_ */

0 comments on commit a5aa0b8

Please sign in to comment.