From f98a9e5d06c080c3560277e0ccf6adbbaf0f7912 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Wed, 23 Feb 2022 08:25:44 +0100 Subject: [PATCH 01/47] Adding hal.py, credentials.py. Modification of __init__.py --- 1_send_data.py | 5 ++- LiveObjects/__init__.py | 1 + LiveObjects/credentials.py | 27 ++++++++++++++++ LiveObjects/hal.py | 66 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 LiveObjects/credentials.py create mode 100644 LiveObjects/hal.py diff --git a/1_send_data.py b/1_send_data.py index 2e05593..dd6ab07 100644 --- a/1_send_data.py +++ b/1_send_data.py @@ -10,8 +10,11 @@ import LiveObjects + +b = LiveObjects.BoardsFactory() +c = b.board.get_lo_id() #Create LiveObjects with parameters: ClientID - Security - APIKEY -lo = LiveObjects.Connection("PythonMQTT", LiveObjects.NONE, "") +lo = LiveObjects.Connection("PythonMQTT", LiveObjects.SSL, "") messageRate = 5 diff --git a/LiveObjects/__init__.py b/LiveObjects/__init__.py index 56f73f8..939a168 100644 --- a/LiveObjects/__init__.py +++ b/LiveObjects/__init__.py @@ -1,4 +1,5 @@ from LiveObjects.Connection import * +from LiveObjects.hal import * import json import time import os diff --git a/LiveObjects/credentials.py b/LiveObjects/credentials.py new file mode 100644 index 0000000..4167da3 --- /dev/null +++ b/LiveObjects/credentials.py @@ -0,0 +1,27 @@ +# +# Copyright (C) Orange +# +# This software is distributed under the terms and conditions of the 'MIT' +# license which can be found in the file 'LICENSE.md' in this package distribution + +NONE = 1 +WIFI = 2 +MOBILE = 3 + + +class Credentials: + def __init__(self, net_type=NONE): + self._lo_id = '0ce12ecdd74343bd9360b63888033de0' + + if net_type == WIFI: + self._wifi_ssid = 'EdekAD57BA' + self._wifi_password = 'JANECZEK2000' + elif net_type == MOBILE: + self._pin = '1155' + self._apn = 'internet' + + def get_credentials(self): + return self + + def get_lo_id(self): + return self._lo_id diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py new file mode 100644 index 0000000..ff1be69 --- /dev/null +++ b/LiveObjects/hal.py @@ -0,0 +1,66 @@ +# +# Copyright (C) Orange +# +# This software is distributed under the terms and conditions of the 'MIT' +# license which can be found in the file 'LICENSE.md' in this package distribution + +import os +from LiveObjects.credentials import Credentials, WIFI, MOBILE + + +class BoardsInterface: + credentials = Credentials().get_credentials() + + def mqtt_lib_import(self, lang): + # https://stackoverflow.com/questions/8718885/import-module-from-string-variable + import_strings = { + 'microPython': 'from umqttrobust import MQTTClient', + 'Python': 'import paho.mqtt.client as paho' + } + return import_strings[lang] + + +class LoPy(BoardsInterface): + pass + + +class GPy(BoardsInterface): + def __init__(self): + self._lang = 'microPython' + self._wifi_tls_capability = True + self._mobile_tls_capability = True + self._mqtt_lib = super().mqtt_lib_import(self._lang) + + +class Esp8266(BoardsInterface): + def __init__(self): + self._lang = 'microPython' + self._wifi_tls_capability = False + self._mqtt_lib = super().mqtt_lib_import(self._lang) + + +class Win32(BoardsInterface): + pass + + +class Esp32(BoardsInterface): + def __init__(self): + self._lang = 'microPython' + self._wifi_tls_capability = True + self._mqtt_lib = super().mqtt_lib_import(self._lang) + + +class Linux(BoardsInterface): + def __init__(self): + self._lang = 'Python' + self._wifi_tls_capability = True + self._mqtt_lib = super().mqtt_lib_import(self._lang) + + +class BoardsFactory: + + def __new__(cls): + sn = os.uname().sysname + sn_u = sn[0].upper() + sn[1:] # first letter upper + board = eval(sn_u)() # instance of board + return board From a521d01b09b0e039ec8ff05eb1d8e0b0d4286f23 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Wed, 23 Feb 2022 18:03:43 +0100 Subject: [PATCH 02/47] refacoring --- 1_send_data.py | 7 +++---- LiveObjects/__init__.py | 2 +- LiveObjects/hal.py | 6 +++--- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/1_send_data.py b/1_send_data.py index dd6ab07..c25bc43 100644 --- a/1_send_data.py +++ b/1_send_data.py @@ -4,17 +4,16 @@ # This software is distributed under the terms and conditions of the 'MIT' # license which can be found in the file 'LICENSE.md' in this package distribution -import os -import sys import time import LiveObjects b = LiveObjects.BoardsFactory() -c = b.board.get_lo_id() +lo_id = LiveObjects.Credentials().get_lo_id() + #Create LiveObjects with parameters: ClientID - Security - APIKEY -lo = LiveObjects.Connection("PythonMQTT", LiveObjects.SSL, "") +lo = LiveObjects.Connection("PythonMQTT", LiveObjects.SSL, lo_id) messageRate = 5 diff --git a/LiveObjects/__init__.py b/LiveObjects/__init__.py index 939a168..553e50c 100644 --- a/LiveObjects/__init__.py +++ b/LiveObjects/__init__.py @@ -3,4 +3,4 @@ import json import time import os -import sys \ No newline at end of file +import sys diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index ff1be69..6b860b0 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -60,7 +60,7 @@ def __init__(self): class BoardsFactory: def __new__(cls): - sn = os.uname().sysname - sn_u = sn[0].upper() + sn[1:] # first letter upper - board = eval(sn_u)() # instance of board + s = os.uname().sysname + sn = s[0].upper() + s[1:] # capitalize first letter + board = eval(sn)() # instance of board return board From 5191b3d9adf8f20eac8d0596a19e67d2d7490398 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Sat, 26 Feb 2022 16:13:33 +0100 Subject: [PATCH 03/47] First step implementation connection w/ network for ESP32 --- 1_send_data.py | 27 +++++------ LiveObjects/Connection.py | 2 +- LiveObjects/__init__.py | 1 + LiveObjects/credentials.py | 17 ++++--- LiveObjects/hal.py | 93 ++++++++++++++++++++++++++++++++++---- 5 files changed, 110 insertions(+), 30 deletions(-) diff --git a/1_send_data.py b/1_send_data.py index c25bc43..9586909 100644 --- a/1_send_data.py +++ b/1_send_data.py @@ -5,25 +5,26 @@ # license which can be found in the file 'LICENSE.md' in this package distribution import time - import LiveObjects +creds = LiveObjects.Credentials() +board = LiveObjects.BoardsFactory() -b = LiveObjects.BoardsFactory() -lo_id = LiveObjects.Credentials().get_lo_id() - -#Create LiveObjects with parameters: ClientID - Security - APIKEY -lo = LiveObjects.Connection("PythonMQTT", LiveObjects.SSL, lo_id) +apikey = creds.get_apikey() +# Create LiveObjects with parameters: Board - ClientID - Security - APIKEY +lo = LiveObjects.Connection(board, "PythonMQTT", LiveObjects.SSL, apikey) messageRate = 5 -#Main program -lo.connect() #Connect to LiveObjects +# Main program +board.network_connect() +lo.connect() # Connect to LiveObjects last = time.time() uptime = time.time() + while True: - if time.time()>=last+messageRate: - lo.addToPayload("uptime", int(time.time() - uptime) ) #Add value to payload: name - value - lo.sendData() #Sending data to cloud - lo.loop() #Check for incoming messages and if connection is still active - last = time.time() \ No newline at end of file + if time.time() >= last+messageRate: + lo.addToPayload("uptime", int(time.time() - uptime)) # Add value to payload: name - value + lo.sendData() # Sending data to cloud + lo.loop() # Check for incoming messages and if connection is still active + last = time.time() diff --git a/LiveObjects/Connection.py b/LiveObjects/Connection.py index 415fcd2..9a27275 100644 --- a/LiveObjects/Connection.py +++ b/LiveObjects/Connection.py @@ -27,7 +27,7 @@ def __init__(self,value,type_, cb = None): self.callback = cb class Connection: - def __init__(self, deviceID, port, apiKey, debug = True): + def __init__(self, board, deviceID, port, apiKey, debug = True): try: if sys.platform == "linux" or sys.platform=="win32": import paho.mqtt.client as paho diff --git a/LiveObjects/__init__.py b/LiveObjects/__init__.py index 553e50c..af16118 100644 --- a/LiveObjects/__init__.py +++ b/LiveObjects/__init__.py @@ -1,5 +1,6 @@ from LiveObjects.Connection import * from LiveObjects.hal import * +from LiveObjects.credentials import * import json import time import os diff --git a/LiveObjects/credentials.py b/LiveObjects/credentials.py index 4167da3..b4973cf 100644 --- a/LiveObjects/credentials.py +++ b/LiveObjects/credentials.py @@ -6,22 +6,25 @@ NONE = 1 WIFI = 2 -MOBILE = 3 +LTE = 3 class Credentials: def __init__(self, net_type=NONE): - self._lo_id = '0ce12ecdd74343bd9360b63888033de0' + self._apikey = '0ce12ecdd74343bd9360b63888033de0' if net_type == WIFI: self._wifi_ssid = 'EdekAD57BA' self._wifi_password = 'JANECZEK2000' - elif net_type == MOBILE: + elif net_type == LTE: self._pin = '1155' self._apn = 'internet' - def get_credentials(self): - return self + def get_apikey(self): + return self._apikey - def get_lo_id(self): - return self._lo_id + def get_wifi_creds(self): + return {'ssid': self._wifi_ssid, 'pass': self._wifi_password} + + def get_lte_creds(self): + return self._pin, self._apn diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index 6b860b0..9f26eda 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -5,13 +5,12 @@ # license which can be found in the file 'LICENSE.md' in this package distribution import os -from LiveObjects.credentials import Credentials, WIFI, MOBILE +import time class BoardsInterface: - credentials = Credentials().get_credentials() - def mqtt_lib_import(self, lang): + def mqtt_lib_import_str(self, lang): # https://stackoverflow.com/questions/8718885/import-module-from-string-variable import_strings = { 'microPython': 'from umqttrobust import MQTTClient', @@ -19,6 +18,12 @@ def mqtt_lib_import(self, lang): } return import_strings[lang] + def network_connect(self, creds): + pass + + def network_disconnect(self): + pass + class LoPy(BoardsInterface): pass @@ -29,14 +34,20 @@ def __init__(self): self._lang = 'microPython' self._wifi_tls_capability = True self._mobile_tls_capability = True - self._mqtt_lib = super().mqtt_lib_import(self._lang) + self._mqtt_lib = super().mqtt_lib_import_str(self._lang) + + def network_connect(self, creds): + pass class Esp8266(BoardsInterface): def __init__(self): self._lang = 'microPython' self._wifi_tls_capability = False - self._mqtt_lib = super().mqtt_lib_import(self._lang) + self._mqtt_lib = super().mqtt_lib_import_str(self._lang) + + def network_connect(self, creds): + pass class Win32(BoardsInterface): @@ -47,20 +58,84 @@ class Esp32(BoardsInterface): def __init__(self): self._lang = 'microPython' self._wifi_tls_capability = True - self._mqtt_lib = super().mqtt_lib_import(self._lang) + self._mqtt_lib = super().mqtt_lib_import_str(self._lang) + + def network_connect(self, creds): + wifi_connect(creds) class Linux(BoardsInterface): def __init__(self): self._lang = 'Python' self._wifi_tls_capability = True - self._mqtt_lib = super().mqtt_lib_import(self._lang) + self._mqtt_lib = super().mqtt_lib_import_str(self._lang) + + def network_connect(self, creds): + use_existing_network_connection() class BoardsFactory: def __new__(cls): s = os.uname().sysname - sn = s[0].upper() + s[1:] # capitalize first letter - board = eval(sn)() # instance of board + sn = s[0].upper() + s[1:] # capitalize first letter + board = eval(sn)() # instance of board return board + + +def use_existing_network_connection(): + print('Using existing network connection') + + +def wifi_connect(creds): + import network + + creds = {'ssid': 'EdekAD57BA', 'pass': 'JANECZEK2000'} + print('444444444444444444444444444') + sta_if = network.WLAN(network.STA_IF) + if not sta_if.isconnected(): + print('connecting to network...') + sta_if.active(True) + sta_if.connect(creds['ssid'], creds['pass']) + while not sta_if.isconnected(): + pass + print('network config:', sta_if.ifconfig()) + + # # ------------------ PyCom -------------------------- + # def pycomConn(self): + # wlan = WLAN(mode=WLAN.STA)#, bandwidth=WLAN.HT20) + # wlan.hostname('xPy_1') + # startTime = time.time() + # while 1: + # print("Trying to connect...") + # wlan.connect(ssid='EdekAD57BA', auth=(WLAN.WPA2, 'JANECZEK2000')) + # time.sleep_ms(3000) + # if wlan.isconnected(): + # print("WiFi connected succesfully") + # print('IPs:', wlan.ifconfig(), 'Channel:', wlan.channel()) + # break + # elif time.time() - startTime > CONN_TIMEOUT: + # print("WiFi not connected. Stopped.") + # break + + +def mobile_connect(pin): + # noinspection PyUnresolvedReferences + from network import LTE + import socket + + lte = LTE() + time.sleep(2) + print("PIN", (lte.send_at_cmd(f'AT+CPIN="{pin}"')).strip()) + + lte.attach() + print("attaching... ", end='') + while not lte.isattached(): + time.sleep(1) + print("attached!") + + lte.connect() + print("connecting... ", end='') + while not lte.isconnected(): + time.sleep(1) + print("connected!") From 7b9f0d3779657443dd47876344173deaacc36bc3 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Sun, 27 Feb 2022 16:22:08 +0100 Subject: [PATCH 04/47] Implementation of network connection for RPi, ESP32, ESP8266. --- 1_send_data.py | 8 +++--- LiveObjects/credentials.py | 15 +++++------ LiveObjects/hal.py | 52 ++++++++++++++++++++++++++------------ 3 files changed, 48 insertions(+), 27 deletions(-) diff --git a/1_send_data.py b/1_send_data.py index 9586909..7c8b586 100644 --- a/1_send_data.py +++ b/1_send_data.py @@ -7,12 +7,14 @@ import time import LiveObjects -creds = LiveObjects.Credentials() board = LiveObjects.BoardsFactory() -apikey = creds.get_apikey() +apikey = board.get_apikey() +client_id = board.get_client_id() +security_level = board.get_security_level() + # Create LiveObjects with parameters: Board - ClientID - Security - APIKEY -lo = LiveObjects.Connection(board, "PythonMQTT", LiveObjects.SSL, apikey) +lo = LiveObjects.Connection(board, client_id, security_level, apikey) messageRate = 5 diff --git a/LiveObjects/credentials.py b/LiveObjects/credentials.py index b4973cf..f0f5181 100644 --- a/LiveObjects/credentials.py +++ b/LiveObjects/credentials.py @@ -3,20 +3,19 @@ # # This software is distributed under the terms and conditions of the 'MIT' # license which can be found in the file 'LICENSE.md' in this package distribution +class Credentials: -NONE = 1 -WIFI = 2 -LTE = 3 - + NONE = 1 + WIFI = 2 + LTE = 3 -class Credentials: def __init__(self, net_type=NONE): self._apikey = '0ce12ecdd74343bd9360b63888033de0' - if net_type == WIFI: + if net_type == Credentials.WIFI: self._wifi_ssid = 'EdekAD57BA' self._wifi_password = 'JANECZEK2000' - elif net_type == LTE: + elif net_type == Credentials.LTE: self._pin = '1155' self._apn = 'internet' @@ -24,7 +23,7 @@ def get_apikey(self): return self._apikey def get_wifi_creds(self): - return {'ssid': self._wifi_ssid, 'pass': self._wifi_password} + return {'ssid': self._wifi_ssid, 'password': self._wifi_password} def get_lte_creds(self): return self._pin, self._apn diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index 9f26eda..dc393f6 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -7,9 +7,21 @@ import os import time +import LiveObjects + class BoardsInterface: + @staticmethod + def create_credentials(mode): + return LiveObjects.Credentials(mode) + + def get_apikey(self): + return self._credentials.get_apikey() + + def get_client_id(self): + return self._lang + 'MQTT' + def mqtt_lib_import_str(self, lang): # https://stackoverflow.com/questions/8718885/import-module-from-string-variable import_strings = { @@ -18,7 +30,10 @@ def mqtt_lib_import_str(self, lang): } return import_strings[lang] - def network_connect(self, creds): + def get_security_level(self): + return LiveObjects.SSL if self._wifi_tls_capability else LiveObjects.NONE + + def network_connect(self): pass def network_disconnect(self): @@ -33,10 +48,10 @@ class GPy(BoardsInterface): def __init__(self): self._lang = 'microPython' self._wifi_tls_capability = True - self._mobile_tls_capability = True + self._lte_tls_capability = True self._mqtt_lib = super().mqtt_lib_import_str(self._lang) - def network_connect(self, creds): + def network_connect(self): pass @@ -44,10 +59,12 @@ class Esp8266(BoardsInterface): def __init__(self): self._lang = 'microPython' self._wifi_tls_capability = False + self._wifi_lte_capability = False self._mqtt_lib = super().mqtt_lib_import_str(self._lang) + self._credentials = super().create_credentials(LiveObjects.Credentials.WIFI) - def network_connect(self, creds): - pass + def network_connect(self): + wifi_connect(self._credentials.get_wifi_creds()['ssid'], self._credentials.get_wifi_creds()['password']) class Win32(BoardsInterface): @@ -58,19 +75,23 @@ class Esp32(BoardsInterface): def __init__(self): self._lang = 'microPython' self._wifi_tls_capability = True + self._wifi_lte_capability = False self._mqtt_lib = super().mqtt_lib_import_str(self._lang) + self._credentials = super().create_credentials(LiveObjects.Credentials.WIFI) - def network_connect(self, creds): - wifi_connect(creds) + def network_connect(self): + wifi_connect(self._credentials.get_wifi_creds()['ssid'], self._credentials.get_wifi_creds()['password']) class Linux(BoardsInterface): def __init__(self): self._lang = 'Python' self._wifi_tls_capability = True + self._wifi_lte_capability = False self._mqtt_lib = super().mqtt_lib_import_str(self._lang) + self._credentials = super().create_credentials(LiveObjects.Credentials.NONE) - def network_connect(self, creds): + def network_connect(self): use_existing_network_connection() @@ -87,18 +108,17 @@ def use_existing_network_connection(): print('Using existing network connection') -def wifi_connect(creds): +def wifi_connect(ssid, password): import network - creds = {'ssid': 'EdekAD57BA', 'pass': 'JANECZEK2000'} - print('444444444444444444444444444') sta_if = network.WLAN(network.STA_IF) - if not sta_if.isconnected(): + sta_if.active(True) + while not sta_if.isconnected(): print('connecting to network...') - sta_if.active(True) - sta_if.connect(creds['ssid'], creds['pass']) - while not sta_if.isconnected(): - pass + sta_if.connect(ssid, password) + if sta_if.isconnected(): + break + time.sleep(2) print('network config:', sta_if.ifconfig()) # # ------------------ PyCom -------------------------- From 42ccd90ecd57ee5f614c326a3feb86a39441bc41 Mon Sep 17 00:00:00 2001 From: Tomasz Malek <81158833+tomekmalek@users.noreply.github.com> Date: Mon, 28 Feb 2022 08:31:33 +0100 Subject: [PATCH 05/47] Update credentials.py --- LiveObjects/credentials.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/LiveObjects/credentials.py b/LiveObjects/credentials.py index f0f5181..c211a30 100644 --- a/LiveObjects/credentials.py +++ b/LiveObjects/credentials.py @@ -10,14 +10,14 @@ class Credentials: LTE = 3 def __init__(self, net_type=NONE): - self._apikey = '0ce12ecdd74343bd9360b63888033de0' + self._apikey = if net_type == Credentials.WIFI: - self._wifi_ssid = 'EdekAD57BA' - self._wifi_password = 'JANECZEK2000' + self._wifi_ssid = + self._wifi_password = elif net_type == Credentials.LTE: - self._pin = '1155' - self._apn = 'internet' + self._pin = + self._apn = def get_apikey(self): return self._apikey From 9e640b5b5c47c4c8b4ed1086bfc502d343797154 Mon Sep 17 00:00:00 2001 From: Tomasz Malek <81158833+tomekmalek@users.noreply.github.com> Date: Mon, 28 Feb 2022 11:06:07 +0100 Subject: [PATCH 06/47] Update hal.py --- LiveObjects/hal.py | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index dc393f6..8ef928a 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -121,24 +121,7 @@ def wifi_connect(ssid, password): time.sleep(2) print('network config:', sta_if.ifconfig()) - # # ------------------ PyCom -------------------------- - # def pycomConn(self): - # wlan = WLAN(mode=WLAN.STA)#, bandwidth=WLAN.HT20) - # wlan.hostname('xPy_1') - # startTime = time.time() - # while 1: - # print("Trying to connect...") - # wlan.connect(ssid='EdekAD57BA', auth=(WLAN.WPA2, 'JANECZEK2000')) - # time.sleep_ms(3000) - # if wlan.isconnected(): - # print("WiFi connected succesfully") - # print('IPs:', wlan.ifconfig(), 'Channel:', wlan.channel()) - # break - # elif time.time() - startTime > CONN_TIMEOUT: - # print("WiFi not connected. Stopped.") - # break - - + def mobile_connect(pin): # noinspection PyUnresolvedReferences from network import LTE From 93a24a11f36194114333ab9084e58133bbd27205 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Mon, 28 Feb 2022 14:53:08 +0100 Subject: [PATCH 07/47] Implementation of network connection for Pycom boards --- LiveObjects/hal.py | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index 8ef928a..c781560 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -50,9 +50,10 @@ def __init__(self): self._wifi_tls_capability = True self._lte_tls_capability = True self._mqtt_lib = super().mqtt_lib_import_str(self._lang) + self._credentials = super().create_credentials(LiveObjects.Credentials.WIFI) def network_connect(self): - pass + pycom_wifi_connect(self._credentials.get_wifi_creds()['ssid'], self._credentials.get_wifi_creds()['password']) class Esp8266(BoardsInterface): @@ -114,14 +115,36 @@ def wifi_connect(ssid, password): sta_if = network.WLAN(network.STA_IF) sta_if.active(True) while not sta_if.isconnected(): - print('connecting to network...') + print('Connecting to network...') sta_if.connect(ssid, password) if sta_if.isconnected(): break time.sleep(2) - print('network config:', sta_if.ifconfig()) + print('Network config:', sta_if.ifconfig()) + + +CONN_TIMEOUT = 20 + + +def pycom_wifi_connect(ssid, password): + from network import WLAN + + wlan = WLAN(mode=WLAN.STA) + wlan.hostname('xPy_1') + start_time = time.time() + while 1: + print("Trying to connect...") + wlan.connect(ssid=ssid, auth=(WLAN.WPA2, password)) + time.sleep_ms(3000) + if wlan.isconnected(): + print("WiFi connected succesfully") + print('IPs:', wlan.ifconfig(), 'Channel:', wlan.channel()) + break + elif time.time() - start_time > CONN_TIMEOUT: + print("WiFi not connected. Stopped.") + break + - def mobile_connect(pin): # noinspection PyUnresolvedReferences from network import LTE From 423f030887a39ef29d0d529fd361336c8ba580b5 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Tue, 1 Mar 2022 08:25:10 +0100 Subject: [PATCH 08/47] Correction of LTE connection method for GPy. --- LiveObjects/credentials.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/LiveObjects/credentials.py b/LiveObjects/credentials.py index c211a30..f0f5181 100644 --- a/LiveObjects/credentials.py +++ b/LiveObjects/credentials.py @@ -10,14 +10,14 @@ class Credentials: LTE = 3 def __init__(self, net_type=NONE): - self._apikey = + self._apikey = '0ce12ecdd74343bd9360b63888033de0' if net_type == Credentials.WIFI: - self._wifi_ssid = - self._wifi_password = + self._wifi_ssid = 'EdekAD57BA' + self._wifi_password = 'JANECZEK2000' elif net_type == Credentials.LTE: - self._pin = - self._apn = + self._pin = '1155' + self._apn = 'internet' def get_apikey(self): return self._apikey From 6c690906ce86fcf440413f21d42c5c881ac8032b Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Tue, 1 Mar 2022 09:50:17 +0100 Subject: [PATCH 09/47] Correction of LTE connection method for GPy. --- LiveObjects/credentials.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/LiveObjects/credentials.py b/LiveObjects/credentials.py index f0f5181..c211a30 100644 --- a/LiveObjects/credentials.py +++ b/LiveObjects/credentials.py @@ -10,14 +10,14 @@ class Credentials: LTE = 3 def __init__(self, net_type=NONE): - self._apikey = '0ce12ecdd74343bd9360b63888033de0' + self._apikey = if net_type == Credentials.WIFI: - self._wifi_ssid = 'EdekAD57BA' - self._wifi_password = 'JANECZEK2000' + self._wifi_ssid = + self._wifi_password = elif net_type == Credentials.LTE: - self._pin = '1155' - self._apn = 'internet' + self._pin = + self._apn = def get_apikey(self): return self._apikey From 11e6c3c132feb8afd8353f8b2fb2cd1ea2fe0fe9 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Tue, 1 Mar 2022 10:04:32 +0100 Subject: [PATCH 10/47] Correction of LTE connection method for GPy. --- LiveObjects/hal.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index c781560..82bab7c 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -22,8 +22,8 @@ def get_apikey(self): def get_client_id(self): return self._lang + 'MQTT' - def mqtt_lib_import_str(self, lang): - # https://stackoverflow.com/questions/8718885/import-module-from-string-variable + @staticmethod + def mqtt_lib_import_str(lang): import_strings = { 'microPython': 'from umqttrobust import MQTTClient', 'Python': 'import paho.mqtt.client as paho' @@ -145,14 +145,14 @@ def pycom_wifi_connect(ssid, password): break -def mobile_connect(pin): - # noinspection PyUnresolvedReferences +def lte_connect(pin): + from network import LTE import socket lte = LTE() time.sleep(2) - print("PIN", (lte.send_at_cmd(f'AT+CPIN="{pin}"')).strip()) + print("PIN", (lte.send_at_cmd('AT+CPIN="%s"' % pin)).strip()) lte.attach() print("attaching... ", end='') From 659e5a5967f4bb61616eafc758e097e54446c932 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Tue, 1 Mar 2022 11:19:57 +0100 Subject: [PATCH 11/47] Changes in way of creation credentials regarding type of network (EXISTING, WIFI, LTE) --- LiveObjects/credentials.py | 13 ++++++------- LiveObjects/hal.py | 12 ++++++++---- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/LiveObjects/credentials.py b/LiveObjects/credentials.py index c211a30..ed76fbd 100644 --- a/LiveObjects/credentials.py +++ b/LiveObjects/credentials.py @@ -3,19 +3,18 @@ # # This software is distributed under the terms and conditions of the 'MIT' # license which can be found in the file 'LICENSE.md' in this package distribution -class Credentials: +import LiveObjects + - NONE = 1 - WIFI = 2 - LTE = 3 +class Credentials: - def __init__(self, net_type=NONE): + def __init__(self, net_type): self._apikey = - if net_type == Credentials.WIFI: + if net_type == LiveObjects.BoardsInterface.WIFI: self._wifi_ssid = self._wifi_password = - elif net_type == Credentials.LTE: + elif net_type == LiveObjects.BoardsInterface.LTE: self._pin = self._apn = diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index 82bab7c..ce84c22 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -12,6 +12,10 @@ class BoardsInterface: + EXISTING = 1 + WIFI = 2 + LTE = 3 + @staticmethod def create_credentials(mode): return LiveObjects.Credentials(mode) @@ -50,7 +54,7 @@ def __init__(self): self._wifi_tls_capability = True self._lte_tls_capability = True self._mqtt_lib = super().mqtt_lib_import_str(self._lang) - self._credentials = super().create_credentials(LiveObjects.Credentials.WIFI) + self._credentials = super().create_credentials(BoardsInterface.WIFI) def network_connect(self): pycom_wifi_connect(self._credentials.get_wifi_creds()['ssid'], self._credentials.get_wifi_creds()['password']) @@ -62,7 +66,7 @@ def __init__(self): self._wifi_tls_capability = False self._wifi_lte_capability = False self._mqtt_lib = super().mqtt_lib_import_str(self._lang) - self._credentials = super().create_credentials(LiveObjects.Credentials.WIFI) + self._credentials = super().create_credentials(BoardsInterface.WIFI) def network_connect(self): wifi_connect(self._credentials.get_wifi_creds()['ssid'], self._credentials.get_wifi_creds()['password']) @@ -78,7 +82,7 @@ def __init__(self): self._wifi_tls_capability = True self._wifi_lte_capability = False self._mqtt_lib = super().mqtt_lib_import_str(self._lang) - self._credentials = super().create_credentials(LiveObjects.Credentials.WIFI) + self._credentials = super().create_credentials(BoardsInterface.WIFI) def network_connect(self): wifi_connect(self._credentials.get_wifi_creds()['ssid'], self._credentials.get_wifi_creds()['password']) @@ -90,7 +94,7 @@ def __init__(self): self._wifi_tls_capability = True self._wifi_lte_capability = False self._mqtt_lib = super().mqtt_lib_import_str(self._lang) - self._credentials = super().create_credentials(LiveObjects.Credentials.NONE) + self._credentials = super().create_credentials(BoardsInterface.EXISTING) def network_connect(self): use_existing_network_connection() From c6deecbc28e3cd866b4088c72cc5e6a677a934cf Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Tue, 1 Mar 2022 11:23:45 +0100 Subject: [PATCH 12/47] Changes in method get_lte_creds in credentials.py --- LiveObjects/credentials.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LiveObjects/credentials.py b/LiveObjects/credentials.py index ed76fbd..2acc651 100644 --- a/LiveObjects/credentials.py +++ b/LiveObjects/credentials.py @@ -25,4 +25,4 @@ def get_wifi_creds(self): return {'ssid': self._wifi_ssid, 'password': self._wifi_password} def get_lte_creds(self): - return self._pin, self._apn + return {'pin': self._pin, 'apn_name': self._apn} From 73056869874ad9e1c6ddae6699ba683e9aedb0eb Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Tue, 1 Mar 2022 15:39:37 +0100 Subject: [PATCH 13/47] Implementation of selecting network carrier (WIFI, LTE). --- 1_send_data.py | 6 ++-- LiveObjects/credentials.py | 14 ++++---- LiveObjects/hal.py | 69 +++++++++++++++++++++++++++----------- 3 files changed, 60 insertions(+), 29 deletions(-) diff --git a/1_send_data.py b/1_send_data.py index 7c8b586..974e23f 100644 --- a/1_send_data.py +++ b/1_send_data.py @@ -7,7 +7,7 @@ import time import LiveObjects -board = LiveObjects.BoardsFactory() +board = LiveObjects.BoardsFactory(net_type=LiveObjects.BoardsInterface.WIFI) apikey = board.get_apikey() client_id = board.get_client_id() @@ -16,7 +16,7 @@ # Create LiveObjects with parameters: Board - ClientID - Security - APIKEY lo = LiveObjects.Connection(board, client_id, security_level, apikey) -messageRate = 5 +MESSAGE_RATE = 5 # Main program board.network_connect() @@ -25,7 +25,7 @@ uptime = time.time() while True: - if time.time() >= last+messageRate: + if time.time() >= last + MESSAGE_RATE: lo.addToPayload("uptime", int(time.time() - uptime)) # Add value to payload: name - value lo.sendData() # Sending data to cloud lo.loop() # Check for incoming messages and if connection is still active diff --git a/LiveObjects/credentials.py b/LiveObjects/credentials.py index 2acc651..4bd2e61 100644 --- a/LiveObjects/credentials.py +++ b/LiveObjects/credentials.py @@ -9,11 +9,13 @@ class Credentials: def __init__(self, net_type): + self._apikey = + self._net_type = net_type if net_type == LiveObjects.BoardsInterface.WIFI: self._wifi_ssid = - self._wifi_password = + self._wifi_password = elif net_type == LiveObjects.BoardsInterface.LTE: self._pin = self._apn = @@ -21,8 +23,8 @@ def __init__(self, net_type): def get_apikey(self): return self._apikey - def get_wifi_creds(self): - return {'ssid': self._wifi_ssid, 'password': self._wifi_password} - - def get_lte_creds(self): - return {'pin': self._pin, 'apn_name': self._apn} + def get_creds(self): + if self._net_type == LiveObjects.BoardsInterface.WIFI: + return {'ssid': self._wifi_ssid, 'password': self._wifi_password} + elif self._net_type == LiveObjects.BoardsInterface.LTE: + return {'pin': self._pin, 'apn_name': self._apn} diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index ce84c22..ad02e8f 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -12,13 +12,13 @@ class BoardsInterface: - EXISTING = 1 - WIFI = 2 - LTE = 3 + EXISTING_NETWORK = 2 + WIFI = 3 + LTE = 4 @staticmethod - def create_credentials(mode): - return LiveObjects.Credentials(mode) + def create_credentials(net_type): + return LiveObjects.Credentials(net_type) def get_apikey(self): return self._credentials.get_apikey() @@ -35,7 +35,7 @@ def mqtt_lib_import_str(lang): return import_strings[lang] def get_security_level(self): - return LiveObjects.SSL if self._wifi_tls_capability else LiveObjects.NONE + pass def network_connect(self): pass @@ -49,27 +49,43 @@ class LoPy(BoardsInterface): class GPy(BoardsInterface): - def __init__(self): + def __init__(self, net_type): self._lang = 'microPython' + self._net_type = net_type self._wifi_tls_capability = True - self._lte_tls_capability = True + self._lte_tls_capability = False self._mqtt_lib = super().mqtt_lib_import_str(self._lang) - self._credentials = super().create_credentials(BoardsInterface.WIFI) + self._credentials = super().create_credentials(net_type) def network_connect(self): - pycom_wifi_connect(self._credentials.get_wifi_creds()['ssid'], self._credentials.get_wifi_creds()['password']) + if self._net_type == BoardsInterface.WIFI: + pycom_wifi_connect(self._credentials.get_creds()['ssid'], self._credentials.get_creds()['password']) + elif self._net_type == BoardsInterface.LTE: + lte_connect(self._credentials.get_creds()['pin']) + + def get_security_level(self): + if self._net_type == BoardsInterface.WIFI: + return LiveObjects.SSL if self._wifi_tls_capability else LiveObjects.NONE + elif self._net_type == BoardsInterface.LTE: + return LiveObjects.SSL if self._lte_tls_capability else LiveObjects.NONE class Esp8266(BoardsInterface): - def __init__(self): + def __init__(self, net_type): self._lang = 'microPython' + self._net_type = net_type self._wifi_tls_capability = False self._wifi_lte_capability = False self._mqtt_lib = super().mqtt_lib_import_str(self._lang) self._credentials = super().create_credentials(BoardsInterface.WIFI) def network_connect(self): - wifi_connect(self._credentials.get_wifi_creds()['ssid'], self._credentials.get_wifi_creds()['password']) + if self._net_type == BoardsInterface.WIFI: + wifi_connect(self._credentials.get_creds()['ssid'], self._credentials.get_creds()['password']) + + def get_security_level(self): + if self._net_type == BoardsInterface.WIFI: + return LiveObjects.SSL if self._wifi_tls_capability else LiveObjects.NONE class Win32(BoardsInterface): @@ -77,35 +93,47 @@ class Win32(BoardsInterface): class Esp32(BoardsInterface): - def __init__(self): + def __init__(self, net_type): self._lang = 'microPython' + self._net_type = net_type self._wifi_tls_capability = True self._wifi_lte_capability = False self._mqtt_lib = super().mqtt_lib_import_str(self._lang) self._credentials = super().create_credentials(BoardsInterface.WIFI) def network_connect(self): - wifi_connect(self._credentials.get_wifi_creds()['ssid'], self._credentials.get_wifi_creds()['password']) + if self._net_type == BoardsInterface.WIFI: + wifi_connect(self._credentials.get_creds()['ssid'], self._credentials.get_creds()['password']) + + def get_security_level(self): + if self._net_type == BoardsInterface.WIFI: + return LiveObjects.SSL if self._wifi_tls_capability else LiveObjects.NONE class Linux(BoardsInterface): - def __init__(self): + def __init__(self, net_type): self._lang = 'Python' + self._net_type = net_type self._wifi_tls_capability = True self._wifi_lte_capability = False self._mqtt_lib = super().mqtt_lib_import_str(self._lang) - self._credentials = super().create_credentials(BoardsInterface.EXISTING) + self._credentials = super().create_credentials(self._net_type) def network_connect(self): - use_existing_network_connection() + if self._net_type == BoardsInterface.EXISTING_NETWORK: + use_existing_network_connection() + + def get_security_level(self): + if self._net_type == BoardsInterface.EXISTING_NETWORK: + return LiveObjects.SSL if self._wifi_tls_capability else LiveObjects.NONE class BoardsFactory: - def __new__(cls): + def __new__(cls, net_type): s = os.uname().sysname sn = s[0].upper() + s[1:] # capitalize first letter - board = eval(sn)() # instance of board + board = eval(sn)(net_type) # instance of board w/ net type: WiFi, LTE, etc. return board @@ -130,6 +158,7 @@ def wifi_connect(ssid, password): CONN_TIMEOUT = 20 +# noinspection PyUnresolvedReferences def pycom_wifi_connect(ssid, password): from network import WLAN @@ -149,10 +178,10 @@ def pycom_wifi_connect(ssid, password): break +# noinspection PyUnresolvedReferences def lte_connect(pin): from network import LTE - import socket lte = LTE() time.sleep(2) From 703a55be8c06e82c8cb8cc568c56e3694f2e7773 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Wed, 2 Mar 2022 11:54:18 +0100 Subject: [PATCH 14/47] Implementation of default network carrier: EXISTING_NETWORK for RPi, WIFI for other boards. For GPy is possible to select LTE instead DEFAULT_CARRIER. --- 1_send_data.py | 2 +- LiveObjects/hal.py | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/1_send_data.py b/1_send_data.py index 974e23f..e7f6744 100644 --- a/1_send_data.py +++ b/1_send_data.py @@ -7,7 +7,7 @@ import time import LiveObjects -board = LiveObjects.BoardsFactory(net_type=LiveObjects.BoardsInterface.WIFI) +board = LiveObjects.BoardsFactory(net_type=LiveObjects.BoardsInterface.DEFAULT_CARRIER) apikey = board.get_apikey() client_id = board.get_client_id() diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index ad02e8f..a5affb6 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -12,6 +12,7 @@ class BoardsInterface: + DEFAULT_CARRIER = 1 EXISTING_NETWORK = 2 WIFI = 3 LTE = 4 @@ -51,11 +52,11 @@ class LoPy(BoardsInterface): class GPy(BoardsInterface): def __init__(self, net_type): self._lang = 'microPython' - self._net_type = net_type + self._net_type = BoardsInterface.WIFI if net_type == BoardsInterface.DEFAULT_CARRIER else net_type self._wifi_tls_capability = True self._lte_tls_capability = False self._mqtt_lib = super().mqtt_lib_import_str(self._lang) - self._credentials = super().create_credentials(net_type) + self._credentials = super().create_credentials(self._net_type) def network_connect(self): if self._net_type == BoardsInterface.WIFI: @@ -73,7 +74,7 @@ def get_security_level(self): class Esp8266(BoardsInterface): def __init__(self, net_type): self._lang = 'microPython' - self._net_type = net_type + self._net_type = BoardsInterface.WIFI if net_type == BoardsInterface.DEFAULT_CARRIER else None self._wifi_tls_capability = False self._wifi_lte_capability = False self._mqtt_lib = super().mqtt_lib_import_str(self._lang) @@ -95,7 +96,7 @@ class Win32(BoardsInterface): class Esp32(BoardsInterface): def __init__(self, net_type): self._lang = 'microPython' - self._net_type = net_type + self._net_type = BoardsInterface.WIFI if net_type == BoardsInterface.DEFAULT_CARRIER else None self._wifi_tls_capability = True self._wifi_lte_capability = False self._mqtt_lib = super().mqtt_lib_import_str(self._lang) @@ -113,7 +114,7 @@ def get_security_level(self): class Linux(BoardsInterface): def __init__(self, net_type): self._lang = 'Python' - self._net_type = net_type + self._net_type = BoardsInterface.EXISTING_NETWORK if net_type == BoardsInterface.DEFAULT_CARRIER else None self._wifi_tls_capability = True self._wifi_lte_capability = False self._mqtt_lib = super().mqtt_lib_import_str(self._lang) From 48d78254db5fb987c19edc5a69a46edc97dca633 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Thu, 3 Mar 2022 10:30:51 +0100 Subject: [PATCH 15/47] Validation of carrier available for every board. --- LiveObjects/hal.py | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index a5affb6..94a7370 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -6,6 +6,7 @@ import os import time +import sys import LiveObjects @@ -38,6 +39,11 @@ def mqtt_lib_import_str(lang): def get_security_level(self): pass + def check_network_capabilities(self, net_type): + if net_type not in self._carrier_capability: + print('Carrier not supported.') + sys.exit() + def network_connect(self): pass @@ -53,12 +59,14 @@ class GPy(BoardsInterface): def __init__(self, net_type): self._lang = 'microPython' self._net_type = BoardsInterface.WIFI if net_type == BoardsInterface.DEFAULT_CARRIER else net_type + self._carrier_capability = (BoardsInterface.WIFI, BoardsInterface.LTE) self._wifi_tls_capability = True self._lte_tls_capability = False self._mqtt_lib = super().mqtt_lib_import_str(self._lang) self._credentials = super().create_credentials(self._net_type) def network_connect(self): + super().check_network_capabilities(self._net_type) if self._net_type == BoardsInterface.WIFI: pycom_wifi_connect(self._credentials.get_creds()['ssid'], self._credentials.get_creds()['password']) elif self._net_type == BoardsInterface.LTE: @@ -74,19 +82,19 @@ def get_security_level(self): class Esp8266(BoardsInterface): def __init__(self, net_type): self._lang = 'microPython' - self._net_type = BoardsInterface.WIFI if net_type == BoardsInterface.DEFAULT_CARRIER else None + self._net_type = BoardsInterface.WIFI if net_type == BoardsInterface.DEFAULT_CARRIER else net_type + self._carrier_capability = (BoardsInterface.WIFI,) self._wifi_tls_capability = False self._wifi_lte_capability = False self._mqtt_lib = super().mqtt_lib_import_str(self._lang) - self._credentials = super().create_credentials(BoardsInterface.WIFI) + self._credentials = super().create_credentials(self._net_type) def network_connect(self): - if self._net_type == BoardsInterface.WIFI: - wifi_connect(self._credentials.get_creds()['ssid'], self._credentials.get_creds()['password']) + super().check_network_capabilities(self._net_type) + wifi_connect(self._credentials.get_creds()['ssid'], self._credentials.get_creds()['password']) def get_security_level(self): - if self._net_type == BoardsInterface.WIFI: - return LiveObjects.SSL if self._wifi_tls_capability else LiveObjects.NONE + return LiveObjects.SSL if self._wifi_tls_capability else LiveObjects.NONE class Win32(BoardsInterface): @@ -96,37 +104,37 @@ class Win32(BoardsInterface): class Esp32(BoardsInterface): def __init__(self, net_type): self._lang = 'microPython' - self._net_type = BoardsInterface.WIFI if net_type == BoardsInterface.DEFAULT_CARRIER else None + self._net_type = BoardsInterface.WIFI if net_type == BoardsInterface.DEFAULT_CARRIER else net_type + self._carrier_capability = (BoardsInterface.WIFI,) self._wifi_tls_capability = True self._wifi_lte_capability = False self._mqtt_lib = super().mqtt_lib_import_str(self._lang) - self._credentials = super().create_credentials(BoardsInterface.WIFI) + self._credentials = super().create_credentials(self._net_type) def network_connect(self): - if self._net_type == BoardsInterface.WIFI: - wifi_connect(self._credentials.get_creds()['ssid'], self._credentials.get_creds()['password']) + super().check_network_capabilities(self._net_type) + wifi_connect(self._credentials.get_creds()['ssid'], self._credentials.get_creds()['password']) def get_security_level(self): - if self._net_type == BoardsInterface.WIFI: - return LiveObjects.SSL if self._wifi_tls_capability else LiveObjects.NONE + return LiveObjects.SSL if self._wifi_tls_capability else LiveObjects.NONE class Linux(BoardsInterface): def __init__(self, net_type): self._lang = 'Python' - self._net_type = BoardsInterface.EXISTING_NETWORK if net_type == BoardsInterface.DEFAULT_CARRIER else None + self._net_type = BoardsInterface.EXISTING_NETWORK if net_type == BoardsInterface.DEFAULT_CARRIER else net_type + self._carrier_capability = (BoardsInterface.EXISTING_NETWORK,) self._wifi_tls_capability = True self._wifi_lte_capability = False self._mqtt_lib = super().mqtt_lib_import_str(self._lang) self._credentials = super().create_credentials(self._net_type) def network_connect(self): - if self._net_type == BoardsInterface.EXISTING_NETWORK: - use_existing_network_connection() + super().check_network_capabilities(self._net_type) + use_existing_network_connection() def get_security_level(self): - if self._net_type == BoardsInterface.EXISTING_NETWORK: - return LiveObjects.SSL if self._wifi_tls_capability else LiveObjects.NONE + return LiveObjects.SSL if self._wifi_tls_capability else LiveObjects.NONE class BoardsFactory: @@ -159,7 +167,6 @@ def wifi_connect(ssid, password): CONN_TIMEOUT = 20 -# noinspection PyUnresolvedReferences def pycom_wifi_connect(ssid, password): from network import WLAN @@ -171,7 +178,7 @@ def pycom_wifi_connect(ssid, password): wlan.connect(ssid=ssid, auth=(WLAN.WPA2, password)) time.sleep_ms(3000) if wlan.isconnected(): - print("WiFi connected succesfully") + print("WiFi connected successfully") print('IPs:', wlan.ifconfig(), 'Channel:', wlan.channel()) break elif time.time() - start_time > CONN_TIMEOUT: @@ -179,7 +186,6 @@ def pycom_wifi_connect(ssid, password): break -# noinspection PyUnresolvedReferences def lte_connect(pin): from network import LTE From a50448a7e1491f689b7966c7d088117758ff24ae Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Thu, 3 Mar 2022 11:18:49 +0100 Subject: [PATCH 16/47] Correction of hal.py removing unusable lte capabilities in concrete classes. --- LiveObjects/hal.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index 94a7370..ac1e166 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -85,7 +85,6 @@ def __init__(self, net_type): self._net_type = BoardsInterface.WIFI if net_type == BoardsInterface.DEFAULT_CARRIER else net_type self._carrier_capability = (BoardsInterface.WIFI,) self._wifi_tls_capability = False - self._wifi_lte_capability = False self._mqtt_lib = super().mqtt_lib_import_str(self._lang) self._credentials = super().create_credentials(self._net_type) @@ -107,7 +106,6 @@ def __init__(self, net_type): self._net_type = BoardsInterface.WIFI if net_type == BoardsInterface.DEFAULT_CARRIER else net_type self._carrier_capability = (BoardsInterface.WIFI,) self._wifi_tls_capability = True - self._wifi_lte_capability = False self._mqtt_lib = super().mqtt_lib_import_str(self._lang) self._credentials = super().create_credentials(self._net_type) @@ -125,7 +123,6 @@ def __init__(self, net_type): self._net_type = BoardsInterface.EXISTING_NETWORK if net_type == BoardsInterface.DEFAULT_CARRIER else net_type self._carrier_capability = (BoardsInterface.EXISTING_NETWORK,) self._wifi_tls_capability = True - self._wifi_lte_capability = False self._mqtt_lib = super().mqtt_lib_import_str(self._lang) self._credentials = super().create_credentials(self._net_type) From a4ecdefc18e94f267e4b18298defb500f50c7c77 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Thu, 3 Mar 2022 16:02:04 +0100 Subject: [PATCH 17/47] Preventing function lte_connect against entering PIN if it had been entered. --- LiveObjects/hal.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index ac1e166..4c4f503 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -61,7 +61,7 @@ def __init__(self, net_type): self._net_type = BoardsInterface.WIFI if net_type == BoardsInterface.DEFAULT_CARRIER else net_type self._carrier_capability = (BoardsInterface.WIFI, BoardsInterface.LTE) self._wifi_tls_capability = True - self._lte_tls_capability = False + self._lte_tls_capability = True self._mqtt_lib = super().mqtt_lib_import_str(self._lang) self._credentials = super().create_credentials(self._net_type) @@ -122,7 +122,7 @@ def __init__(self, net_type): self._lang = 'Python' self._net_type = BoardsInterface.EXISTING_NETWORK if net_type == BoardsInterface.DEFAULT_CARRIER else net_type self._carrier_capability = (BoardsInterface.EXISTING_NETWORK,) - self._wifi_tls_capability = True + self._existing_network_tls_capability = True self._mqtt_lib = super().mqtt_lib_import_str(self._lang) self._credentials = super().create_credentials(self._net_type) @@ -131,7 +131,7 @@ def network_connect(self): use_existing_network_connection() def get_security_level(self): - return LiveObjects.SSL if self._wifi_tls_capability else LiveObjects.NONE + return LiveObjects.SSL if self._existing_network_tls_capability else LiveObjects.NONE class BoardsFactory: @@ -187,9 +187,19 @@ def lte_connect(pin): from network import LTE + def is_waiting_for_pin(): + if lte.send_at_cmd('AT+CPIN?').strip() == '+CPIN: SIM PIN\r\n\r\nOK': + return True + else: + return False + lte = LTE() time.sleep(2) - print("PIN", (lte.send_at_cmd('AT+CPIN="%s"' % pin)).strip()) + + if is_waiting_for_pin(): + print("PIN", (lte.send_at_cmd('AT+CPIN="%s"' % pin)).strip()) + else: + print("PIN READY") lte.attach() print("attaching... ", end='') From 6fae563f48cebf7413dfb30154f54a52a6a99add Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Fri, 4 Mar 2022 11:24:04 +0100 Subject: [PATCH 18/47] Switching to the current endpoint: mqtt.liveobjects.orange-business.com. --- LiveObjects/Connection.py | 9 +++++---- LiveObjects/hal.py | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/LiveObjects/Connection.py b/LiveObjects/Connection.py index 9a27275..099f53f 100644 --- a/LiveObjects/Connection.py +++ b/LiveObjects/Connection.py @@ -42,7 +42,7 @@ def __init__(self, board, deviceID, port, apiKey, debug = True): self.__port = port self.__apiKey = apiKey self.__parameters = {} - self.__server = "liveobjects.orange-business.com" + self.__server = "mqtt.liveobjects.orange-business.com" self.__topic = "dev/data" self.__value = "value" self.__payload = {self.__value: {}} @@ -54,7 +54,7 @@ def __init__(self, board, deviceID, port, apiKey, debug = True): self.__mqtt = paho.Client(deviceID) else: self.ssl = port == 8883 - self.__mqtt = MQTTClient(deviceID, self.__server, self.__port, "json+device", self.__apiKey, 0, self.ssl, {}) + self.__mqtt = MQTTClient(deviceID, self.__server, self.__port, "json+device", self.__apiKey, 0, self.ssl, {'server_hostname':self.__server}) def loop(self): if self.mode == 0: @@ -107,8 +107,9 @@ def connect(self): self.__mqtt.on_connect = self.__onConnect self.__mqtt.on_message = self.__onMessage if self.__port == 8883: - dirname = os.path.dirname(__file__) - filename = os.path.join(dirname, "./certfile.cer") + # dirname = os.path.dirname(__file__) + # filename = os.path.join(dirname, "./certfile.cer") + filename = "/etc/ssl/certs/ca-certificates.crt" self.__mqtt.tls_set(filename) self.__mqtt.connect(self.__server, self.__port, 60) self.__mqtt.loop_start() diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index 4c4f503..efed19a 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -199,16 +199,16 @@ def is_waiting_for_pin(): if is_waiting_for_pin(): print("PIN", (lte.send_at_cmd('AT+CPIN="%s"' % pin)).strip()) else: - print("PIN READY") + print("PIN PRESENT OK") lte.attach() - print("attaching... ", end='') + print("Attaching... ", end='') while not lte.isattached(): time.sleep(1) print("attached!") lte.connect() - print("connecting... ", end='') + print("Connecting... ", end='') while not lte.isconnected(): time.sleep(1) print("connected!") From 3992f5e9cb0bc7ce3cbcec03a8a975ee7ebb0251 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Fri, 4 Mar 2022 12:13:02 +0100 Subject: [PATCH 19/47] Small Connection.py refactoring due to be according to PEPs. --- LiveObjects/Connection.py | 60 +++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/LiveObjects/Connection.py b/LiveObjects/Connection.py index 099f53f..917d17e 100644 --- a/LiveObjects/Connection.py +++ b/LiveObjects/Connection.py @@ -8,24 +8,26 @@ import json import time import os -INT="i32" -UINT="u32" -BINARY="bin" -STRING="str" -FLOAT="f64" -INFO="INFO" +INT = "i32" +UINT = "u32" +BINARY = "bin" +STRING = "str" +FLOAT = "f64" +INFO = "INFO" WARNING = "WARNING" ERROR = "ERROR" SSL = 8883 NONE = 1883 + class LiveObjectsParameter: - def __init__(self,value,type_, cb = None): + def __init__(self, value, type_, cb=None): self.value = value self.type = type_ self.callback = cb + class Connection: def __init__(self, board, deviceID, port, apiKey, debug = True): try: @@ -48,7 +50,7 @@ def __init__(self, board, deviceID, port, apiKey, debug = True): self.__payload = {self.__value: {}} self.__commands = {} self.__doLog = debug - self.quit=False + self.quit = False if self.mode == 1: self.__mqtt = paho.Client(deviceID) @@ -60,7 +62,7 @@ def loop(self): if self.mode == 0: self.__mqtt.check_msg() - def __onMessage(self,client="", userdata="", msg=""): + def __onMessage(self, client="", userdata="", msg=""): if self.mode == 1: if msg.topic == "dev/cfg/upd": self.__parameterManager(msg) @@ -72,14 +74,14 @@ def __onMessage(self,client="", userdata="", msg=""): elif client == b"dev/cmd": self.__commandManager(userdata) - def __onConnect(self,client="", userdata="", flags="", rc=""): + def __onConnect(self, client="", userdata="", flags="", rc=""): if self.mode == 1: - if rc ==0: - self.outputDebug(INFO,"Connected!") - if len(self.__commands)>0: + if rc == 0: + self.outputDebug(INFO, "Connected!") + if len(self.__commands) > 0: self.outputDebug(INFO, "Subscribing commands") self.__mqtt.subscribe("dev/cmd") - if len(self.__parameters)>0: + if len(self.__parameters) > 0: self.outputDebug(INFO, "Subscribing parameters") self.__mqtt.subscribe("dev/cfg/upd") self.__sendConfig() @@ -107,8 +109,6 @@ def connect(self): self.__mqtt.on_connect = self.__onConnect self.__mqtt.on_message = self.__onMessage if self.__port == 8883: - # dirname = os.path.dirname(__file__) - # filename = os.path.join(dirname, "./certfile.cer") filename = "/etc/ssl/certs/ca-certificates.crt" self.__mqtt.tls_set(filename) self.__mqtt.connect(self.__server, self.__port, 60) @@ -133,8 +133,8 @@ def outputDebug(self,info, *args): def addCommand(self, name, cmd): self.__commands[name] = cmd - def __commandManager(self,msg): - if self.mode ==1: + def __commandManager(self, msg): + if self.mode == 1: msgDict = json.loads(msg.payload) self.outputDebug(INFO, "Received message:\n", json.dumps(msgDict, sort_keys=True, indent=4)) else: @@ -149,18 +149,18 @@ def __commandManager(self,msg): def __default(self, req=""): self.outputDebug(INFO, "Command not found!") - return {"info" : "Command not found"} + return {"info": "Command not found"} def __sendConfig(self): - outMsg={ "cfg" : {} } + outMsg = { "cfg" : {} } for param in self.__parameters: - outMsg["cfg"][param]={ "t" : self.__parameters[param].type, "v" : self.__parameters[param].value } - self.__publishMessage("dev/cfg",outMsg) + outMsg["cfg"][param] = {"t": self.__parameters[param].type, "v": self.__parameters[param].value} + self.__publishMessage("dev/cfg", outMsg) def __parameterManager(self, msg): if self.mode == 1: - self.outputDebug(INFO,"Received message: ") - self.outputDebug(INFO,json.loads(msg.payload)) + self.outputDebug(INFO, "Received message: ") + self.outputDebug(INFO, json.loads(msg.payload)) params = json.loads(msg.payload) else: self.outputDebug(INFO, "Received message: ") @@ -179,9 +179,9 @@ def __parameterManager(self, msg): self.__parameters[param].type = FLOAT self.__parameters[param].value = params["cfg"][param]["v"] - if self.__parameters[param].callback != None: + if self.__parameters[param].callback != None: self.__parameters[param].callback(param, params["cfg"][param]["v"]) - self.__publishMessage("dev/cfg",params) + self.__publishMessage("dev/cfg", params) def addParameter(self, name, val, type_, cb=None): if type_ == INT: @@ -196,7 +196,7 @@ def addParameter(self, name, val, type_, cb=None): val = float(val) self.__parameters[name] = LiveObjectsParameter(val, type_, cb) - def getParameter(self,name): + def getParameter(self, name): if self.__parameters[name].type == INT: return int(self.__parameters[name].value) elif self.__parameters[name].type == STRING: @@ -220,12 +220,12 @@ def addModel(self, model): def addTag(self, tag): if not "tags" in self.__payload: - self.__payload["tags"]=[] + self.__payload["tags"] = [] self.__payload["tags"].append(tag) def addTags(self, tags): if not "tags" in self.__payload: - self.__payload["tags"]=[] + self.__payload["tags"] = [] for tag in tags: self.__payload["tags"].append(tag) @@ -234,7 +234,7 @@ def sendData(self): sys.exit() self.__publishMessage("dev/data",self.__payload) self.__payload = {} - self.__payload[self.__value]={} + self.__payload[self.__value] = {} def __publishMessage(self, topic, msg): self.outputDebug(INFO, "Publishing message on topic: ", topic) From c68fc474af20b25f80ebdd289a51f44a8818808e Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Fri, 4 Mar 2022 12:29:59 +0100 Subject: [PATCH 20/47] Small refactoring. --- LiveObjects/Connection.py | 4 ++-- LiveObjects/hal.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/LiveObjects/Connection.py b/LiveObjects/Connection.py index 917d17e..0e629ae 100644 --- a/LiveObjects/Connection.py +++ b/LiveObjects/Connection.py @@ -29,9 +29,9 @@ def __init__(self, value, type_, cb=None): class Connection: - def __init__(self, board, deviceID, port, apiKey, debug = True): + def __init__(self, board, deviceID, port, apiKey, debug=True): try: - if sys.platform == "linux" or sys.platform=="win32": + if sys.platform == "linux" or sys.platform == "win32": import paho.mqtt.client as paho import os self.mode = 1 diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index efed19a..cedc3ba 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -187,7 +187,7 @@ def lte_connect(pin): from network import LTE - def is_waiting_for_pin(): + def is_sim_waiting_for_pin(): if lte.send_at_cmd('AT+CPIN?').strip() == '+CPIN: SIM PIN\r\n\r\nOK': return True else: @@ -196,10 +196,10 @@ def is_waiting_for_pin(): lte = LTE() time.sleep(2) - if is_waiting_for_pin(): + if is_sim_waiting_for_pin(): print("PIN", (lte.send_at_cmd('AT+CPIN="%s"' % pin)).strip()) else: - print("PIN PRESENT OK") + print("PIN PRESENT: OK") lte.attach() print("Attaching... ", end='') From aa33ba3713e8cc0121f6813b11fb1cb7ef2ac471 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Mon, 7 Mar 2022 11:56:28 +0100 Subject: [PATCH 21/47] Changing field 'lang' to 'lang_id'. Changes in respective methods. --- LiveObjects/hal.py | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index cedc3ba..d9e9a1f 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -18,6 +18,9 @@ class BoardsInterface: WIFI = 3 LTE = 4 + PYTHON = 1 + MICROPYTHON = 2 + @staticmethod def create_credentials(net_type): return LiveObjects.Credentials(net_type) @@ -26,15 +29,20 @@ def get_apikey(self): return self._credentials.get_apikey() def get_client_id(self): - return self._lang + 'MQTT' + return self.get_lang_str() + 'MQTT' - @staticmethod - def mqtt_lib_import_str(lang): - import_strings = { - 'microPython': 'from umqttrobust import MQTTClient', - 'Python': 'import paho.mqtt.client as paho' - } - return import_strings[lang] + def get_lang_str(self): + lang_dict = {BoardsInterface.PYTHON: 'Python', + BoardsInterface.MICROPYTHON: 'microPython'} + return lang_dict[self._lang_id] + + def get_lang_id(self): + return self._lang_id + + def mqtt_lib_import_str(self): + import_strings = {BoardsInterface.PYTHON: 'import paho.mqtt.client as paho', + BoardsInterface.MICROPYTHON: 'from umqttrobust import MQTTClient'} + return import_strings[self._lang_id] def get_security_level(self): pass @@ -57,12 +65,12 @@ class LoPy(BoardsInterface): class GPy(BoardsInterface): def __init__(self, net_type): - self._lang = 'microPython' + self._lang_id = BoardsInterface.MICROPYTHON self._net_type = BoardsInterface.WIFI if net_type == BoardsInterface.DEFAULT_CARRIER else net_type self._carrier_capability = (BoardsInterface.WIFI, BoardsInterface.LTE) self._wifi_tls_capability = True self._lte_tls_capability = True - self._mqtt_lib = super().mqtt_lib_import_str(self._lang) + self._mqtt_lib = super().mqtt_lib_import_str() self._credentials = super().create_credentials(self._net_type) def network_connect(self): @@ -81,11 +89,11 @@ def get_security_level(self): class Esp8266(BoardsInterface): def __init__(self, net_type): - self._lang = 'microPython' + self._lang_id = BoardsInterface.MICROPYTHON self._net_type = BoardsInterface.WIFI if net_type == BoardsInterface.DEFAULT_CARRIER else net_type self._carrier_capability = (BoardsInterface.WIFI,) self._wifi_tls_capability = False - self._mqtt_lib = super().mqtt_lib_import_str(self._lang) + self._mqtt_lib = super().mqtt_lib_import_str() self._credentials = super().create_credentials(self._net_type) def network_connect(self): @@ -102,11 +110,11 @@ class Win32(BoardsInterface): class Esp32(BoardsInterface): def __init__(self, net_type): - self._lang = 'microPython' + self._lang_id = BoardsInterface.MICROPYTHON self._net_type = BoardsInterface.WIFI if net_type == BoardsInterface.DEFAULT_CARRIER else net_type self._carrier_capability = (BoardsInterface.WIFI,) self._wifi_tls_capability = True - self._mqtt_lib = super().mqtt_lib_import_str(self._lang) + self._mqtt_lib = super().mqtt_lib_import_str() self._credentials = super().create_credentials(self._net_type) def network_connect(self): @@ -119,11 +127,11 @@ def get_security_level(self): class Linux(BoardsInterface): def __init__(self, net_type): - self._lang = 'Python' + self._lang_id = BoardsInterface.PYTHON self._net_type = BoardsInterface.EXISTING_NETWORK if net_type == BoardsInterface.DEFAULT_CARRIER else net_type self._carrier_capability = (BoardsInterface.EXISTING_NETWORK,) self._existing_network_tls_capability = True - self._mqtt_lib = super().mqtt_lib_import_str(self._lang) + self._mqtt_lib = super().mqtt_lib_import_str() self._credentials = super().create_credentials(self._net_type) def network_connect(self): From 191be45974262a7c3f3d950f57696e318f17cb50 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Mon, 7 Mar 2022 13:58:14 +0100 Subject: [PATCH 22/47] First step of integration Factory design pattern with existing module Connection.py. 'self.mode' field contains now language identifier (PYTHON, MICROPYTHON). --- LiveObjects/Connection.py | 48 ++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/LiveObjects/Connection.py b/LiveObjects/Connection.py index 0e629ae..4932d81 100644 --- a/LiveObjects/Connection.py +++ b/LiveObjects/Connection.py @@ -7,7 +7,9 @@ import sys import json import time -import os + +import LiveObjects + INT = "i32" UINT = "u32" BINARY = "bin" @@ -30,17 +32,18 @@ def __init__(self, value, type_, cb=None): class Connection: def __init__(self, board, deviceID, port, apiKey, debug=True): - try: - if sys.platform == "linux" or sys.platform == "win32": + self.mode = board.get_lang_id() + + try: + if self.mode == LiveObjects.BoardsInterface.PYTHON: import paho.mqtt.client as paho import os - self.mode = 1 - else: + elif self.mode == LiveObjects.BoardsInterface.MICROPYTHON: from umqttrobust import MQTTClient - self.mode = 0 except ImportError: - print("[ERROR] U have missing libraries Paho-mqtt(for Linux) or umqttrobust(for uPython)") + print("[ERROR] U have missing libraries Paho-mqtt(for Python) or umqttrobust(for uPython)") sys.exit() + self.__port = port self.__apiKey = apiKey self.__parameters = {} @@ -52,18 +55,19 @@ def __init__(self, board, deviceID, port, apiKey, debug=True): self.__doLog = debug self.quit = False - if self.mode == 1: + if self.mode == LiveObjects.BoardsInterface.PYTHON: self.__mqtt = paho.Client(deviceID) else: self.ssl = port == 8883 - self.__mqtt = MQTTClient(deviceID, self.__server, self.__port, "json+device", self.__apiKey, 0, self.ssl, {'server_hostname':self.__server}) + self.__mqtt = MQTTClient(deviceID, self.__server, self.__port, "json+device", + self.__apiKey, 0, self.ssl, {'server_hostname': self.__server}) def loop(self): - if self.mode == 0: + if self.mode == LiveObjects.BoardsInterface.MICROPYTHON: self.__mqtt.check_msg() def __onMessage(self, client="", userdata="", msg=""): - if self.mode == 1: + if self.mode == LiveObjects.BoardsInterface.PYTHON: if msg.topic == "dev/cfg/upd": self.__parameterManager(msg) elif msg.topic == "dev/cmd": @@ -75,7 +79,7 @@ def __onMessage(self, client="", userdata="", msg=""): self.__commandManager(userdata) def __onConnect(self, client="", userdata="", flags="", rc=""): - if self.mode == 1: + if self.mode == LiveObjects.BoardsInterface.PYTHON: if rc == 0: self.outputDebug(INFO, "Connected!") if len(self.__commands) > 0: @@ -104,7 +108,7 @@ def __onConnect(self, client="", userdata="", flags="", rc=""): def connect(self): - if self.mode == 1: + if self.mode == LiveObjects.BoardsInterface.PYTHON: self.__mqtt.username_pw_set("json+device", self.__apiKey) self.__mqtt.on_connect = self.__onConnect self.__mqtt.on_message = self.__onMessage @@ -123,7 +127,7 @@ def disconnect(self): self.__mqtt.disconnect() self.outputDebug(INFO, "Disconnected") - def outputDebug(self,info, *args): + def outputDebug(self, info, *args): if self.__doLog: print("[", info, "]", end=" ", sep="") for arg in args: @@ -134,7 +138,7 @@ def addCommand(self, name, cmd): self.__commands[name] = cmd def __commandManager(self, msg): - if self.mode == 1: + if self.mode == LiveObjects.BoardsInterface.PYTHON: msgDict = json.loads(msg.payload) self.outputDebug(INFO, "Received message:\n", json.dumps(msgDict, sort_keys=True, indent=4)) else: @@ -152,13 +156,13 @@ def __default(self, req=""): return {"info": "Command not found"} def __sendConfig(self): - outMsg = { "cfg" : {} } + outMsg = {"cfg": {}} for param in self.__parameters: outMsg["cfg"][param] = {"t": self.__parameters[param].type, "v": self.__parameters[param].value} self.__publishMessage("dev/cfg", outMsg) def __parameterManager(self, msg): - if self.mode == 1: + if self.mode == LiveObjects.BoardsInterface.PYTHON: self.outputDebug(INFO, "Received message: ") self.outputDebug(INFO, json.loads(msg.payload)) params = json.loads(msg.payload) @@ -179,8 +183,8 @@ def __parameterManager(self, msg): self.__parameters[param].type = FLOAT self.__parameters[param].value = params["cfg"][param]["v"] - if self.__parameters[param].callback != None: - self.__parameters[param].callback(param, params["cfg"][param]["v"]) + if self.__parameters[param].callback is not None: + self.__parameters[param].callback(param, params["cfg"][param]["v"]) self.__publishMessage("dev/cfg", params) def addParameter(self, name, val, type_, cb=None): @@ -232,14 +236,16 @@ def addTags(self, tags): def sendData(self): if self.quit: sys.exit() - self.__publishMessage("dev/data",self.__payload) + self.__publishMessage("dev/data", self.__payload) self.__payload = {} self.__payload[self.__value] = {} def __publishMessage(self, topic, msg): self.outputDebug(INFO, "Publishing message on topic: ", topic) - if self.mode == 1: + + if self.mode == LiveObjects.BoardsInterface.PYTHON: self.outputDebug(INFO, "\n", json.dumps(msg, sort_keys=True, indent=4)) else: self.outputDebug(INFO, json.dumps(msg)) + self.__mqtt.publish(topic, json.dumps(msg)) From 8fb2d8abb84b0ad9df99e3afae2643f44a64181c Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Mon, 7 Mar 2022 14:10:53 +0100 Subject: [PATCH 23/47] First step of integration Factory design pattern with existing module Connection.py. Checking 'self.mode' field for MICROPYTHON (elif) has been added instead (else). --- LiveObjects/Connection.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/LiveObjects/Connection.py b/LiveObjects/Connection.py index 4932d81..184375e 100644 --- a/LiveObjects/Connection.py +++ b/LiveObjects/Connection.py @@ -57,7 +57,7 @@ def __init__(self, board, deviceID, port, apiKey, debug=True): if self.mode == LiveObjects.BoardsInterface.PYTHON: self.__mqtt = paho.Client(deviceID) - else: + elif self.mode == LiveObjects.BoardsInterface.MICROPYTHON: self.ssl = port == 8883 self.__mqtt = MQTTClient(deviceID, self.__server, self.__port, "json+device", self.__apiKey, 0, self.ssl, {'server_hostname': self.__server}) @@ -72,7 +72,7 @@ def __onMessage(self, client="", userdata="", msg=""): self.__parameterManager(msg) elif msg.topic == "dev/cmd": self.__commandManager(msg) - else: + elif self.mode == LiveObjects.BoardsInterface.MICROPYTHON: if client == b"dev/cfg/upd": self.__parameterManager(userdata) elif client == b"dev/cmd": @@ -96,7 +96,7 @@ def __onConnect(self, client="", userdata="", flags="", rc=""): #else: #self.outputDebug(ERROR,"Unknown error while connecting,quitting...") #sys.exit() - else: + elif self.mode == LiveObjects.BoardsInterface.MICROPYTHON: self.outputDebug(INFO, "Connected, sending config") if len(self.__commands) > 0: self.outputDebug(INFO, "Subscribing commands") @@ -117,7 +117,7 @@ def connect(self): self.__mqtt.tls_set(filename) self.__mqtt.connect(self.__server, self.__port, 60) self.__mqtt.loop_start() - else: + elif self.mode == LiveObjects.BoardsInterface.MICROPYTHON: self.__mqtt.set_callback(self.__onMessage) self.__mqtt.connect() time.sleep(1) @@ -141,7 +141,7 @@ def __commandManager(self, msg): if self.mode == LiveObjects.BoardsInterface.PYTHON: msgDict = json.loads(msg.payload) self.outputDebug(INFO, "Received message:\n", json.dumps(msgDict, sort_keys=True, indent=4)) - else: + elif self.mode == LiveObjects.BoardsInterface.MICROPYTHON: msgDict = json.loads(msg) self.outputDebug(INFO, "Received message:", json.dumps(msgDict)) outputMsg = {} @@ -166,10 +166,11 @@ def __parameterManager(self, msg): self.outputDebug(INFO, "Received message: ") self.outputDebug(INFO, json.loads(msg.payload)) params = json.loads(msg.payload) - else: + elif self.mode == LiveObjects.BoardsInterface.MICROPYTHON: self.outputDebug(INFO, "Received message: ") self.outputDebug(INFO, json.loads(msg)) params = json.loads(msg) + for param in params["cfg"]: if params["cfg"][param]["t"] == "i32": self.__parameters[param].type = INT @@ -245,7 +246,7 @@ def __publishMessage(self, topic, msg): if self.mode == LiveObjects.BoardsInterface.PYTHON: self.outputDebug(INFO, "\n", json.dumps(msg, sort_keys=True, indent=4)) - else: + elif self.mode == LiveObjects.BoardsInterface.MICROPYTHON: self.outputDebug(INFO, json.dumps(msg)) self.__mqtt.publish(topic, json.dumps(msg)) From 9f3316f95c8732431c1c37e08a2947b58ebada19 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Thu, 10 Mar 2022 13:20:06 +0100 Subject: [PATCH 24/47] Overriding method wait_msg() in MQTTClient class to avoid infinite waiting of broker response. Works on all micropython boards but needs improvement because it adds timeout to MESSAGE_RATE. --- LiveObjects/Connection.py | 43 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/LiveObjects/Connection.py b/LiveObjects/Connection.py index 184375e..c803d97 100644 --- a/LiveObjects/Connection.py +++ b/LiveObjects/Connection.py @@ -59,8 +59,47 @@ def __init__(self, board, deviceID, port, apiKey, debug=True): self.__mqtt = paho.Client(deviceID) elif self.mode == LiveObjects.BoardsInterface.MICROPYTHON: self.ssl = port == 8883 - self.__mqtt = MQTTClient(deviceID, self.__server, self.__port, "json+device", - self.__apiKey, 0, self.ssl, {'server_hostname': self.__server}) + + class MQTTClient2(MQTTClient): # overriding original method wait_msg due to infinite waiting + def wait_msg(self): + import select + poller = select.poll() + poller.register(self.sock, select.POLLIN) + res = poller.poll(1000) + if not res: + res = None + self.sock.setblocking(True) + if res is None: + return None + if res == b"": + raise OSError(-1) + if res == b"\xd0": # PINGRESP + sz = self.sock.read(1)[0] + assert sz == 0 + return None + op = res[0] + if op & 0xf0 != 0x30: + return op + sz = self._recv_len() + topic_len = self.sock.read(2) + topic_len = (topic_len[0] << 8) | topic_len[1] + topic = self.sock.read(topic_len) + sz -= topic_len + 2 + if op & 6: + pid = self.sock.read(2) + pid = pid[0] << 8 | pid[1] + sz -= 2 + msg = self.sock.read(sz) + self.cb(topic, msg) + if op & 6 == 2: + pkt = bytearray(b"\x40\x02\0\0") + struct.pack_into("!H", pkt, 2, pid) + self.sock.write(pkt) + elif op & 6 == 4: + assert 0 + + self.__mqtt = MQTTClient2(deviceID, self.__server, self.__port, "json+device", + self.__apiKey, 0, self.ssl, {'server_hostname': self.__server}) def loop(self): if self.mode == LiveObjects.BoardsInterface.MICROPYTHON: From 1c5d07b257f81dd1361a35bcba9c232beb05f1f8 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Fri, 11 Mar 2022 15:26:11 +0100 Subject: [PATCH 25/47] From BoardsInterface class (hal.py) method 'mqtt_lib_import_str' has been removed as unnecessary. Improving class MQTTClient2 containing overridden method 'wait_msg' which implements timeout for waiting for broker answer. Example file 1_send_data.py has been changed to avoid adding timeout concerning waiting for broker answer to MESSAGE_RATE. --- 1_send_data.py | 7 +++---- LiveObjects/Connection.py | 13 +++++++------ LiveObjects/hal.py | 9 --------- 3 files changed, 10 insertions(+), 19 deletions(-) diff --git a/1_send_data.py b/1_send_data.py index e7f6744..7874aa1 100644 --- a/1_send_data.py +++ b/1_send_data.py @@ -21,12 +21,11 @@ # Main program board.network_connect() lo.connect() # Connect to LiveObjects -last = time.time() -uptime = time.time() +last = uptime = time.time() while True: - if time.time() >= last + MESSAGE_RATE: + if (time.time()) >= last + MESSAGE_RATE: lo.addToPayload("uptime", int(time.time() - uptime)) # Add value to payload: name - value lo.sendData() # Sending data to cloud - lo.loop() # Check for incoming messages and if connection is still active last = time.time() + lo.loop() # Check for incoming messages and if connection is still active diff --git a/LiveObjects/Connection.py b/LiveObjects/Connection.py index c803d97..807c84d 100644 --- a/LiveObjects/Connection.py +++ b/LiveObjects/Connection.py @@ -58,14 +58,15 @@ def __init__(self, board, deviceID, port, apiKey, debug=True): if self.mode == LiveObjects.BoardsInterface.PYTHON: self.__mqtt = paho.Client(deviceID) elif self.mode == LiveObjects.BoardsInterface.MICROPYTHON: - self.ssl = port == 8883 - class MQTTClient2(MQTTClient): # overriding original method wait_msg due to infinite waiting - def wait_msg(self): + class MQTTClient2(MQTTClient): + TIMEOUT = 1000 # [ms] + + def wait_msg(self): # overriding original method wait_msg due to avoid infinite waiting import select poller = select.poll() poller.register(self.sock, select.POLLIN) - res = poller.poll(1000) + res = poller.poll(MQTTClient2.TIMEOUT) if not res: res = None self.sock.setblocking(True) @@ -98,6 +99,7 @@ def wait_msg(self): elif op & 6 == 4: assert 0 + self.ssl = port == SSL self.__mqtt = MQTTClient2(deviceID, self.__server, self.__port, "json+device", self.__apiKey, 0, self.ssl, {'server_hostname': self.__server}) @@ -145,13 +147,12 @@ def __onConnect(self, client="", userdata="", flags="", rc=""): self.__mqtt.subscribe(b"dev/cfg/upd") self.__sendConfig() - def connect(self): if self.mode == LiveObjects.BoardsInterface.PYTHON: self.__mqtt.username_pw_set("json+device", self.__apiKey) self.__mqtt.on_connect = self.__onConnect self.__mqtt.on_message = self.__onMessage - if self.__port == 8883: + if self.__port == SSL: filename = "/etc/ssl/certs/ca-certificates.crt" self.__mqtt.tls_set(filename) self.__mqtt.connect(self.__server, self.__port, 60) diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index d9e9a1f..3303a09 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -39,11 +39,6 @@ def get_lang_str(self): def get_lang_id(self): return self._lang_id - def mqtt_lib_import_str(self): - import_strings = {BoardsInterface.PYTHON: 'import paho.mqtt.client as paho', - BoardsInterface.MICROPYTHON: 'from umqttrobust import MQTTClient'} - return import_strings[self._lang_id] - def get_security_level(self): pass @@ -70,7 +65,6 @@ def __init__(self, net_type): self._carrier_capability = (BoardsInterface.WIFI, BoardsInterface.LTE) self._wifi_tls_capability = True self._lte_tls_capability = True - self._mqtt_lib = super().mqtt_lib_import_str() self._credentials = super().create_credentials(self._net_type) def network_connect(self): @@ -93,7 +87,6 @@ def __init__(self, net_type): self._net_type = BoardsInterface.WIFI if net_type == BoardsInterface.DEFAULT_CARRIER else net_type self._carrier_capability = (BoardsInterface.WIFI,) self._wifi_tls_capability = False - self._mqtt_lib = super().mqtt_lib_import_str() self._credentials = super().create_credentials(self._net_type) def network_connect(self): @@ -114,7 +107,6 @@ def __init__(self, net_type): self._net_type = BoardsInterface.WIFI if net_type == BoardsInterface.DEFAULT_CARRIER else net_type self._carrier_capability = (BoardsInterface.WIFI,) self._wifi_tls_capability = True - self._mqtt_lib = super().mqtt_lib_import_str() self._credentials = super().create_credentials(self._net_type) def network_connect(self): @@ -131,7 +123,6 @@ def __init__(self, net_type): self._net_type = BoardsInterface.EXISTING_NETWORK if net_type == BoardsInterface.DEFAULT_CARRIER else net_type self._carrier_capability = (BoardsInterface.EXISTING_NETWORK,) self._existing_network_tls_capability = True - self._mqtt_lib = super().mqtt_lib_import_str() self._credentials = super().create_credentials(self._net_type) def network_connect(self): From 0cc7f5bddc3471144e91155835e1697d351a2e3c Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Mon, 14 Mar 2022 14:43:21 +0100 Subject: [PATCH 26/47] Simplifying example code '1_send_data.py' by moving initialization part to module 'Connection.py'. --- 1_send_data.py | 10 +--------- LiveObjects/Connection.py | 17 ++++++++++------- LiveObjects/hal.py | 10 +++++----- 3 files changed, 16 insertions(+), 21 deletions(-) diff --git a/1_send_data.py b/1_send_data.py index 7874aa1..423b9f0 100644 --- a/1_send_data.py +++ b/1_send_data.py @@ -7,19 +7,11 @@ import time import LiveObjects -board = LiveObjects.BoardsFactory(net_type=LiveObjects.BoardsInterface.DEFAULT_CARRIER) - -apikey = board.get_apikey() -client_id = board.get_client_id() -security_level = board.get_security_level() - -# Create LiveObjects with parameters: Board - ClientID - Security - APIKEY -lo = LiveObjects.Connection(board, client_id, security_level, apikey) +lo = LiveObjects.Connection() MESSAGE_RATE = 5 # Main program -board.network_connect() lo.connect() # Connect to LiveObjects last = uptime = time.time() diff --git a/LiveObjects/Connection.py b/LiveObjects/Connection.py index 807c84d..bd960fd 100644 --- a/LiveObjects/Connection.py +++ b/LiveObjects/Connection.py @@ -31,8 +31,9 @@ def __init__(self, value, type_, cb=None): class Connection: - def __init__(self, board, deviceID, port, apiKey, debug=True): - self.mode = board.get_lang_id() + def __init__(self, debug=True): + self.__board = LiveObjects.BoardsFactory(net_type=LiveObjects.BoardsInterface.DEFAULT_CARRIER) + self.mode = self.__board.get_lang_id() try: if self.mode == LiveObjects.BoardsInterface.PYTHON: @@ -44,8 +45,9 @@ def __init__(self, board, deviceID, port, apiKey, debug=True): print("[ERROR] U have missing libraries Paho-mqtt(for Python) or umqttrobust(for uPython)") sys.exit() - self.__port = port - self.__apiKey = apiKey + self.__port = self.__board.get_security_level() + self.__apiKey = self.__board.get_apikey() + self.__device_id = self.__board.get_client_id() self.__parameters = {} self.__server = "mqtt.liveobjects.orange-business.com" self.__topic = "dev/data" @@ -56,7 +58,7 @@ def __init__(self, board, deviceID, port, apiKey, debug=True): self.quit = False if self.mode == LiveObjects.BoardsInterface.PYTHON: - self.__mqtt = paho.Client(deviceID) + self.__mqtt = paho.Client(self.__device_id) elif self.mode == LiveObjects.BoardsInterface.MICROPYTHON: class MQTTClient2(MQTTClient): @@ -99,8 +101,8 @@ def wait_msg(self): # overriding original method wait_msg due to avoid infin elif op & 6 == 4: assert 0 - self.ssl = port == SSL - self.__mqtt = MQTTClient2(deviceID, self.__server, self.__port, "json+device", + self.ssl = self.__port == SSL + self.__mqtt = MQTTClient2(self.__device_id, self.__server, self.__port, "json+device", self.__apiKey, 0, self.ssl, {'server_hostname': self.__server}) def loop(self): @@ -148,6 +150,7 @@ def __onConnect(self, client="", userdata="", flags="", rc=""): self.__sendConfig() def connect(self): + self.__board.connect() if self.mode == LiveObjects.BoardsInterface.PYTHON: self.__mqtt.username_pw_set("json+device", self.__apiKey) self.__mqtt.on_connect = self.__onConnect diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index 3303a09..f6782cd 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -47,7 +47,7 @@ def check_network_capabilities(self, net_type): print('Carrier not supported.') sys.exit() - def network_connect(self): + def connect(self): pass def network_disconnect(self): @@ -67,7 +67,7 @@ def __init__(self, net_type): self._lte_tls_capability = True self._credentials = super().create_credentials(self._net_type) - def network_connect(self): + def connect(self): super().check_network_capabilities(self._net_type) if self._net_type == BoardsInterface.WIFI: pycom_wifi_connect(self._credentials.get_creds()['ssid'], self._credentials.get_creds()['password']) @@ -89,7 +89,7 @@ def __init__(self, net_type): self._wifi_tls_capability = False self._credentials = super().create_credentials(self._net_type) - def network_connect(self): + def connect(self): super().check_network_capabilities(self._net_type) wifi_connect(self._credentials.get_creds()['ssid'], self._credentials.get_creds()['password']) @@ -109,7 +109,7 @@ def __init__(self, net_type): self._wifi_tls_capability = True self._credentials = super().create_credentials(self._net_type) - def network_connect(self): + def connect(self): super().check_network_capabilities(self._net_type) wifi_connect(self._credentials.get_creds()['ssid'], self._credentials.get_creds()['password']) @@ -125,7 +125,7 @@ def __init__(self, net_type): self._existing_network_tls_capability = True self._credentials = super().create_credentials(self._net_type) - def network_connect(self): + def connect(self): super().check_network_capabilities(self._net_type) use_existing_network_connection() From 6e88b72c4cc24858c933766638be673d810cfa45 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Thu, 17 Mar 2022 15:16:20 +0100 Subject: [PATCH 27/47] All example codes (5) have been refactored and adapted to new conception. Previously prepared modification connected to 'wait_msg' method has been cancelled because it doesn't work with all examples - therefore on GPy there is necessary to switch off TLS mode both for Wi-Fi and LTE. Examples have been checked on Python (Linux) and microPython boards (ESP32, ESP8266 and GPy: both on Wi-Fi and LTE). --- 1_send_data.py | 13 +++++----- 2_simple_parameters.py | 30 +++++++++++------------ 3_parameter_with_callback.py | 35 +++++++++++++-------------- 4_simple_command.py | 35 +++++++++++++-------------- 5_command_with_arguments.py | 46 ++++++++++++++++++------------------ LiveObjects/Connection.py | 43 +-------------------------------- LiveObjects/hal.py | 4 ++-- 7 files changed, 81 insertions(+), 125 deletions(-) diff --git a/1_send_data.py b/1_send_data.py index 423b9f0..36b1106 100644 --- a/1_send_data.py +++ b/1_send_data.py @@ -7,17 +7,18 @@ import time import LiveObjects +# Create LiveObjects lo = LiveObjects.Connection() MESSAGE_RATE = 5 # Main program -lo.connect() # Connect to LiveObjects +lo.connect() # Connect to LiveObjects last = uptime = time.time() while True: - if (time.time()) >= last + MESSAGE_RATE: - lo.addToPayload("uptime", int(time.time() - uptime)) # Add value to payload: name - value - lo.sendData() # Sending data to cloud - last = time.time() - lo.loop() # Check for incoming messages and if connection is still active + if (time.time()) >= last + MESSAGE_RATE: + lo.addToPayload("uptime", int(time.time() - uptime)) # Add value to payload: name - value + lo.sendData() # Sending data to cloud + last = time.time() + lo.loop() # Check for incoming messages and if connection is still active diff --git a/2_simple_parameters.py b/2_simple_parameters.py index 2cf9b7a..b89237c 100644 --- a/2_simple_parameters.py +++ b/2_simple_parameters.py @@ -4,24 +4,22 @@ # This software is distributed under the terms and conditions of the 'MIT' # license which can be found in the file 'LICENSE.md' in this package distribution -import os -import sys import time - import LiveObjects -#Create LiveObjects with parameters: ClientID - Security - APIKEY -lo = LiveObjects.Connection("PythonMQTT", LiveObjects.NONE, "") +# Create LiveObjects +lo = LiveObjects.Connection() + +# Main program +# Available types: INT, BINARY, STRING, FLOAT +lo.addParameter("messageRate", 5, LiveObjects.INT) # Add parameter: Name - Value - Type + +lo.connect() # Connect to LiveObjects +last = uptime = time.time() -#Main program -lo.addParameter("messageRate", 5 , LiveObjects.INT) #Add parameter: Name - Value - Type -#Available types: INT BINARY STRING FLOAT -lo.connect() #Connect to LiveObjects -last = time.time() -uptime = time.time() while True: - if time.time()>=last+lo.getParameter("messageRate"):#Get the parameter using its name - lo.addToPayload("uptime", int(time.time() - uptime) ) #Add value to payload: name - value - lo.sendData() #Sending data to cloud - lo.loop() #Check for incoming messages and if connection is still active - last = time.time() \ No newline at end of file + if time.time() >= last + lo.getParameter("messageRate"): # Get the parameter using its name + lo.addToPayload("uptime", int(time.time() - uptime)) # Add value to payload: name - value + lo.sendData() # Sending data to cloud + last = time.time() + lo.loop() # Check for incoming messages and if connection is still active diff --git a/3_parameter_with_callback.py b/3_parameter_with_callback.py index a9858a1..00fc58f 100644 --- a/3_parameter_with_callback.py +++ b/3_parameter_with_callback.py @@ -4,30 +4,29 @@ # This software is distributed under the terms and conditions of the 'MIT' # license which can be found in the file 'LICENSE.md' in this package distribution -import os -import sys -import time +import time import LiveObjects -#Create LiveObjects with parameters: ClientID - Security - APIKEY -lo = LiveObjects.Connection("PythonMQTT", LiveObjects.NONE, "") +# Create LiveObjects +lo = LiveObjects.Connection() -#Callback for a parameter change + +# Callback for a parameter change def callback(parameterName, newValue): - print("Changed value of the parameter "+parameterName+" to " + str(newValue)) + print("Changed value of the parameter " + parameterName + " to " + str(newValue)) + +# Main program +# Available types: INT, BINARY, STRING, FLOAT +lo.addParameter("messageRate", 5, LiveObjects.INT, callback) # Add parameter: Name - Value - Type - Callback +lo.connect() # Connect to LiveObjects +last = uptime = time.time() -#Main program -lo.addParameter("messageRate", 5 , LiveObjects.INT, callback) #Add parameter: Name - Value - Type - Callback -#Available types: INT BINARY STRING FLOAT -lo.connect() #Connect to LiveObjects -last = time.time() -uptime = time.time() while True: - if time.time()>=last+lo.getParameter("messageRate"):#Get the parameter using its name - lo.addToPayload("uptime", int(time.time() - uptime) ) #Add value to payload: name - value - lo.sendData() #Sending data to cloud - lo.loop() #Check for incoming messages and if connection is still active - last = time.time() \ No newline at end of file + if time.time() >= last + lo.getParameter("messageRate"): # Get the parameter using its name + lo.addToPayload("uptime", int(time.time() - uptime)) # Add value to payload: name - value + lo.sendData() # Sending data to cloud + last = time.time() + lo.loop() # Check for incoming messages and if connection is still active diff --git a/4_simple_command.py b/4_simple_command.py index 65f649f..04a77e0 100644 --- a/4_simple_command.py +++ b/4_simple_command.py @@ -4,30 +4,29 @@ # This software is distributed under the terms and conditions of the 'MIT' # license which can be found in the file 'LICENSE.md' in this package distribution -import os -import sys import time - import LiveObjects -#Create LiveObjects with parameters: ClientID - Security - APIKEY -lo = LiveObjects.Connection("PythonMQTT", LiveObjects.NONE, "") +# Create LiveObjects +lo = LiveObjects.Connection() + +MESSAGE_RATE = 5 -messageRate = 5 -#Define command function +# Define command function def foo(arg={}): - lo.outputDebug(LiveObjects.INFO,"Called function foo") + lo.outputDebug(LiveObjects.INFO, "Called function foo") return {} -#Main program -lo.addCommand("foo",foo) #Add command to LiveObjects: name - function -lo.connect() #Connect to LiveObjects -last = time.time() -uptime = time.time() + +# Main program +lo.addCommand("foo", foo) # Add command to LiveObjects: name - function +lo.connect() # Connect to LiveObjects +last = uptime = time.time() + while True: - if time.time()>=last+messageRate: - lo.addToPayload("uptime", int(time.time() - uptime) ) #Add value to payload: name - value - lo.sendData() #Sending data to cloud - lo.loop() #Check for incoming messages and if connection is still active - last = time.time() \ No newline at end of file + if time.time() >= last + MESSAGE_RATE: + lo.addToPayload("uptime", int(time.time() - uptime)) # Add value to payload: name - value + lo.sendData() # Sending data to cloud + last = time.time() + lo.loop() # Check for incoming messages and if connection is still active diff --git a/5_command_with_arguments.py b/5_command_with_arguments.py index 12bc0b9..c6f93e9 100644 --- a/5_command_with_arguments.py +++ b/5_command_with_arguments.py @@ -4,34 +4,34 @@ # This software is distributed under the terms and conditions of the 'MIT' # license which can be found in the file 'LICENSE.md' in this package distribution -import os -import sys import time import json import LiveObjects -#Create LiveObjects with parameters: ClientID - Security - APIKEY -lo = LiveObjects.Connection("PythonMQTT", LiveObjects.NONE, "") +# Create LiveObjects +lo = LiveObjects.Connection() -messageRate = 5 +MESSAGE_RATE = 5 -#Define command function with arguments handling + +# Define command function with arguments handling def foo(args={}): - lo.outputDebug(LiveObjects.INFO,"Called function foo with args", json.dumps(args)) - counter = 0 - for i in range(args["repetitions"]): - print("Repetition nr "+str(i)) - counter+=1 - return { "Repeated" : str(counter)+" times"} - -#Main program -lo.addCommand("foo",foo) #Add command to LiveObjects: name - function -lo.connect() #Connect to LiveObjects -last = time.time() -uptime = time.time() + lo.outputDebug(LiveObjects.INFO, "Called function foo with args", json.dumps(args)) + counter = 0 + for i in range(args["repetitions"]): + print("Repetition nr " + str(i)) + counter += 1 + return {"Repeated": str(counter) + " times"} + + +# Main program +lo.addCommand("foo", foo) # Add command to LiveObjects: name - function +lo.connect() # Connect to LiveObjects +last = uptime = time.time() + while True: - if time.time()>=last+messageRate: - lo.addToPayload("uptime", int(time.time() - uptime) ) #Add value to payload: name - value - lo.sendData() #Sending data to cloud - lo.loop() #Check for incoming messages and if connection is still active - last = time.time() \ No newline at end of file + if time.time() >= last + MESSAGE_RATE: + lo.addToPayload("uptime", int(time.time() - uptime)) # Add value to payload: name - value + lo.sendData() # Sending data to cloud + last = time.time() + lo.loop() # Check for incoming messages and if connection is still active diff --git a/LiveObjects/Connection.py b/LiveObjects/Connection.py index bd960fd..1bc5646 100644 --- a/LiveObjects/Connection.py +++ b/LiveObjects/Connection.py @@ -60,49 +60,8 @@ def __init__(self, debug=True): if self.mode == LiveObjects.BoardsInterface.PYTHON: self.__mqtt = paho.Client(self.__device_id) elif self.mode == LiveObjects.BoardsInterface.MICROPYTHON: - - class MQTTClient2(MQTTClient): - TIMEOUT = 1000 # [ms] - - def wait_msg(self): # overriding original method wait_msg due to avoid infinite waiting - import select - poller = select.poll() - poller.register(self.sock, select.POLLIN) - res = poller.poll(MQTTClient2.TIMEOUT) - if not res: - res = None - self.sock.setblocking(True) - if res is None: - return None - if res == b"": - raise OSError(-1) - if res == b"\xd0": # PINGRESP - sz = self.sock.read(1)[0] - assert sz == 0 - return None - op = res[0] - if op & 0xf0 != 0x30: - return op - sz = self._recv_len() - topic_len = self.sock.read(2) - topic_len = (topic_len[0] << 8) | topic_len[1] - topic = self.sock.read(topic_len) - sz -= topic_len + 2 - if op & 6: - pid = self.sock.read(2) - pid = pid[0] << 8 | pid[1] - sz -= 2 - msg = self.sock.read(sz) - self.cb(topic, msg) - if op & 6 == 2: - pkt = bytearray(b"\x40\x02\0\0") - struct.pack_into("!H", pkt, 2, pid) - self.sock.write(pkt) - elif op & 6 == 4: - assert 0 - self.ssl = self.__port == SSL - self.__mqtt = MQTTClient2(self.__device_id, self.__server, self.__port, "json+device", + self.__mqtt = MQTTClient(self.__device_id, self.__server, self.__port, "json+device", self.__apiKey, 0, self.ssl, {'server_hostname': self.__server}) def loop(self): diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index f6782cd..f7cdbbd 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -63,8 +63,8 @@ def __init__(self, net_type): self._lang_id = BoardsInterface.MICROPYTHON self._net_type = BoardsInterface.WIFI if net_type == BoardsInterface.DEFAULT_CARRIER else net_type self._carrier_capability = (BoardsInterface.WIFI, BoardsInterface.LTE) - self._wifi_tls_capability = True - self._lte_tls_capability = True + self._wifi_tls_capability = False + self._lte_tls_capability = False self._credentials = super().create_credentials(self._net_type) def connect(self): From c6c6b522d4782b1ac1c5b5ae133ba1e0ae423f38 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Mon, 21 Mar 2022 11:30:58 +0100 Subject: [PATCH 28/47] Adding os_id field for Python. --- LiveObjects/hal.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index f7cdbbd..261177a 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -21,6 +21,9 @@ class BoardsInterface: PYTHON = 1 MICROPYTHON = 2 + WINDOWS = 1 + LINUX = 2 + @staticmethod def create_credentials(net_type): return LiveObjects.Credentials(net_type) @@ -39,6 +42,9 @@ def get_lang_str(self): def get_lang_id(self): return self._lang_id + def get_os_id(self): + pass + def get_security_level(self): pass @@ -120,6 +126,7 @@ def get_security_level(self): class Linux(BoardsInterface): def __init__(self, net_type): self._lang_id = BoardsInterface.PYTHON + self._os_id = BoardsInterface.LINUX self._net_type = BoardsInterface.EXISTING_NETWORK if net_type == BoardsInterface.DEFAULT_CARRIER else net_type self._carrier_capability = (BoardsInterface.EXISTING_NETWORK,) self._existing_network_tls_capability = True @@ -132,6 +139,9 @@ def connect(self): def get_security_level(self): return LiveObjects.SSL if self._existing_network_tls_capability else LiveObjects.NONE + def get_os_id(self): + return self._os_id + class BoardsFactory: From 7fa92110dfbbf252033344e25140641c5c0a8863 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Mon, 21 Mar 2022 12:09:38 +0100 Subject: [PATCH 29/47] Changing way of recognition of board OS. --- LiveObjects/hal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index 261177a..fb21e34 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -146,7 +146,7 @@ def get_os_id(self): class BoardsFactory: def __new__(cls, net_type): - s = os.uname().sysname + s = sys.platform sn = s[0].upper() + s[1:] # capitalize first letter board = eval(sn)(net_type) # instance of board w/ net type: WiFi, LTE, etc. return board From bfcb6272bea120c4a96ebacbbc9f6ec6e6a0b5e0 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Mon, 21 Mar 2022 11:43:13 +0100 Subject: [PATCH 30/47] Adding Windows client support --- LiveObjects/Connection.py | 11 ++++++++++- LiveObjects/hal.py | 18 +++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/LiveObjects/Connection.py b/LiveObjects/Connection.py index 1bc5646..c454e39 100644 --- a/LiveObjects/Connection.py +++ b/LiveObjects/Connection.py @@ -42,7 +42,7 @@ def __init__(self, debug=True): elif self.mode == LiveObjects.BoardsInterface.MICROPYTHON: from umqttrobust import MQTTClient except ImportError: - print("[ERROR] U have missing libraries Paho-mqtt(for Python) or umqttrobust(for uPython)") + print("[ERROR] U have missing libraries 'Paho-mqtt' (for Python) or 'umqttrobust' (for uPython)") sys.exit() self.__port = self.__board.get_security_level() @@ -116,6 +116,15 @@ def connect(self): self.__mqtt.on_message = self.__onMessage if self.__port == SSL: filename = "/etc/ssl/certs/ca-certificates.crt" + + if self.__board.get_os_id() == LiveObjects.BoardsInterface.WINDOWS: + try: + import certifi + filename = certifi.where() + except ImportError: + print("[ERROR] U have missing library 'python-certifi-win32'") + sys.exit() + self.__mqtt.tls_set(filename) self.__mqtt.connect(self.__server, self.__port, 60) self.__mqtt.loop_start() diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index fb21e34..07fef83 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -104,7 +104,23 @@ def get_security_level(self): class Win32(BoardsInterface): - pass + def __init__(self, net_type): + self._lang_id = BoardsInterface.PYTHON + self._os_id = BoardsInterface.WINDOWS + self._net_type = BoardsInterface.EXISTING_NETWORK if net_type == BoardsInterface.DEFAULT_CARRIER else net_type + self._carrier_capability = (BoardsInterface.EXISTING_NETWORK,) + self._existing_network_tls_capability = True + self._credentials = super().create_credentials(self._net_type) + + def connect(self): + super().check_network_capabilities(self._net_type) + use_existing_network_connection() + + def get_security_level(self): + return LiveObjects.SSL if self._existing_network_tls_capability else LiveObjects.NONE + + def get_os_id(self): + return self._os_id class Esp32(BoardsInterface): From 9717b78b0901d78bd2a478f9a76cee5c33503fb0 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Mon, 21 Mar 2022 13:18:15 +0100 Subject: [PATCH 31/47] Moving part of code responsible for determining of certificate store filename from Connection.py to hal.py --- LiveObjects/Connection.py | 12 +----------- LiveObjects/hal.py | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/LiveObjects/Connection.py b/LiveObjects/Connection.py index c454e39..3e33515 100644 --- a/LiveObjects/Connection.py +++ b/LiveObjects/Connection.py @@ -115,17 +115,7 @@ def connect(self): self.__mqtt.on_connect = self.__onConnect self.__mqtt.on_message = self.__onMessage if self.__port == SSL: - filename = "/etc/ssl/certs/ca-certificates.crt" - - if self.__board.get_os_id() == LiveObjects.BoardsInterface.WINDOWS: - try: - import certifi - filename = certifi.where() - except ImportError: - print("[ERROR] U have missing library 'python-certifi-win32'") - sys.exit() - - self.__mqtt.tls_set(filename) + self.__mqtt.tls_set(self.__board.get_store_cert_filename()) self.__mqtt.connect(self.__server, self.__port, 60) self.__mqtt.loop_start() elif self.mode == LiveObjects.BoardsInterface.MICROPYTHON: diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index 07fef83..ae39b3a 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -48,6 +48,9 @@ def get_os_id(self): def get_security_level(self): pass + def get_store_cert_filename(self): + pass + def check_network_capabilities(self, net_type): if net_type not in self._carrier_capability: print('Carrier not supported.') @@ -122,6 +125,14 @@ def get_security_level(self): def get_os_id(self): return self._os_id + def get_store_cert_filename(self): + try: + import certifi + return certifi.where() + except ImportError: + print("[ERROR] U have missing library 'python-certifi-win32'") + sys.exit() + class Esp32(BoardsInterface): def __init__(self, net_type): @@ -147,6 +158,7 @@ def __init__(self, net_type): self._carrier_capability = (BoardsInterface.EXISTING_NETWORK,) self._existing_network_tls_capability = True self._credentials = super().create_credentials(self._net_type) + self._cert_store_filename = "/etc/ssl/certs/ca-certificates.crt" def connect(self): super().check_network_capabilities(self._net_type) @@ -158,6 +170,9 @@ def get_security_level(self): def get_os_id(self): return self._os_id + def get_store_cert_filename(self): + return self._cert_store_filename + class BoardsFactory: From 3ee4ed47deb97938a0983c629dbc1cdd552bd5d6 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Tue, 22 Mar 2022 13:22:19 +0100 Subject: [PATCH 32/47] Adding hostname as a parameter in 'pycom_wifi_connect'. --- LiveObjects/hal.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index ae39b3a..d2d3c4a 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -21,9 +21,6 @@ class BoardsInterface: PYTHON = 1 MICROPYTHON = 2 - WINDOWS = 1 - LINUX = 2 - @staticmethod def create_credentials(net_type): return LiveObjects.Credentials(net_type) @@ -42,9 +39,6 @@ def get_lang_str(self): def get_lang_id(self): return self._lang_id - def get_os_id(self): - pass - def get_security_level(self): pass @@ -75,11 +69,13 @@ def __init__(self, net_type): self._wifi_tls_capability = False self._lte_tls_capability = False self._credentials = super().create_credentials(self._net_type) + self._hostname = 'GPy' def connect(self): super().check_network_capabilities(self._net_type) if self._net_type == BoardsInterface.WIFI: - pycom_wifi_connect(self._credentials.get_creds()['ssid'], self._credentials.get_creds()['password']) + pycom_wifi_connect(self._credentials.get_creds()['ssid'], self._credentials.get_creds()['password'], + self._hostname) elif self._net_type == BoardsInterface.LTE: lte_connect(self._credentials.get_creds()['pin']) @@ -109,7 +105,6 @@ def get_security_level(self): class Win32(BoardsInterface): def __init__(self, net_type): self._lang_id = BoardsInterface.PYTHON - self._os_id = BoardsInterface.WINDOWS self._net_type = BoardsInterface.EXISTING_NETWORK if net_type == BoardsInterface.DEFAULT_CARRIER else net_type self._carrier_capability = (BoardsInterface.EXISTING_NETWORK,) self._existing_network_tls_capability = True @@ -153,7 +148,6 @@ def get_security_level(self): class Linux(BoardsInterface): def __init__(self, net_type): self._lang_id = BoardsInterface.PYTHON - self._os_id = BoardsInterface.LINUX self._net_type = BoardsInterface.EXISTING_NETWORK if net_type == BoardsInterface.DEFAULT_CARRIER else net_type self._carrier_capability = (BoardsInterface.EXISTING_NETWORK,) self._existing_network_tls_capability = True @@ -178,7 +172,7 @@ class BoardsFactory: def __new__(cls, net_type): s = sys.platform - sn = s[0].upper() + s[1:] # capitalize first letter + sn = s[0].upper() + s[1:] # capitalize first letter board = eval(sn)(net_type) # instance of board w/ net type: WiFi, LTE, etc. return board @@ -204,11 +198,11 @@ def wifi_connect(ssid, password): CONN_TIMEOUT = 20 -def pycom_wifi_connect(ssid, password): +def pycom_wifi_connect(ssid, password, hostname): from network import WLAN wlan = WLAN(mode=WLAN.STA) - wlan.hostname('xPy_1') + wlan.hostname(hostname) start_time = time.time() while 1: print("Trying to connect...") From 5a73bc9a430ddc9295f3ab3cff44fc885ece6102 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Tue, 22 Mar 2022 16:16:52 +0100 Subject: [PATCH 33/47] Update README.md --- README.md | 218 +++++++++++++++++++++++++----------------------------- 1 file changed, 100 insertions(+), 118 deletions(-) diff --git a/README.md b/README.md index bcfc303..ef72985 100644 --- a/README.md +++ b/README.md @@ -4,56 +4,57 @@ This code wraps all the functions necessary to make your object work with Live Objects. You can declare parameters, which you can later update OTA from Live objects. You can also create commands to trigger actions remotely. - Only thing u must do yourself is connecting the board with internet. + Only thing you must do yourself is connecting the board with internet. Code uses MQTT connection to exchange data with Live objects under the hood to keep your parameters up to date or execute the commands received without you having to take care of them (apart from writing the code of these commands, of course). ## Compatibility ## -| System | MQTT | MQTTS | -| :--- | :---: | :---: | -| Linux | OK |OK | -| Windows | OK |OK | -| Raspberry Pi | OK |OK | -| ESP8266 | OK | - | -| ESP32 | OK | OK | - -## Prerequisites/dependecies ## -This code needs a few libraries to run +| System | Connectivity | MQTT | MQTTS | +|:--------------|-----------------|:----:|:-----:| +| Linux | Delivered by OS | OK | OK | +| Windows | Delivered by OS | OK | OK | +| Raspberry Pi | Delivered by OS | OK | OK | +| ESP8266 | WiFi | OK | - | +| ESP32 | WiFi | OK | OK | +| LoPy (Pycom) | WiFi | OK | - | +| GPy (Pycom) | WiFi, LTE | OK | - | + +## Prerequisites / dependecies ## +This code needs a few libraries to run: - Python needs [paho-mqtt](https://pypi.org/project/paho-mqtt/) + - Python for Windows needs [python-certifi-win32](https://pypi.org/project/python-certifi-win32/) - uPython needs [umqttsimple, umqttrobust and ssl](https://github.com/micropython/micropython-lib) ## How to use ## -1. Log in to [Live Objects](https://liveobjects.orange-business.com) or request a [trial account](https://liveobjects.orange-business.com/#/request_account) (up to 10 devices for 1 year) if you don't have one. -2. Create an [API key](https://liveobjects.orange-business.com/#/administration/apikeys) for your device. Give it a name, select the *Device access* role and validate. Copy the key. -3. Clone or download the directory from Github. -4. Change **\** in sketches to one you generated -5. Run script +1. Log in to [Live Objects](https://liveobjects.orange-business.com) or request a [trial account](https://liveobjects.orange-business.com/#/request_account) (up to 10 devices for 1 year) if you don't have one, +2. Create an [API key](https://liveobjects.orange-business.com/#/administration/apikeys) for your device. Give it a name, select the *Device access* role and validate. Copy the key, +3. Clone or download the directory from Github, +4. Change **\** in `credentials.py` to one you generated, +5. Run selected `.py` script ## Developer guide ## ### Constructor ### -Constructor of LiveObjects looks like this +Constructor of LiveObjects looks like below: ```Python -lo = LiveObjects.Connection("mqttID",LiveObjects.NONE,"", debug = True) +lo = LiveObjects.Connection() ``` -First parameter is ID of the device, second is type of connection security ( NONE / SSL), third is Api Key to LiveObjects and last is debug mode, if you don't want to output debug messages set it to False. You can also use `lo.setDebug(False)`. - ### Debug messages ### You can use LiveObjects to output debug messages. ```Python -foo = 21 -#INFO / ERROR / WARNING -lo.outputDebug(LiveObjects.INFO,"example value", foo, ...) -#Output: [INFO] example value 21 ... +VALUE = 21 +# INFO / ERROR / WARNING +lo.outputDebug(LiveObjects.INFO, "example value", VALUE, ...) +# Output: [INFO] example value 21 ... ``` ### Declare parameters ### -You can update over the air some parameters of your sketch using Live Objects's parameters. Parameters and Commands must be declared **before** your device connects to Live Objects. +You can update over the air some parameters of your script using Live Objects's parameters. Parameters and Commands must be declared **before** your device connects to Live Objects. You can declare parameters with the `addParameter()` instruction, which accepts the following arguments: - the label of your parameter as it will be displayed on Live Objects; @@ -66,24 +67,24 @@ To retrieve a parameter use function `getParameter()` which takes following argu Example: ```Python -lo.addParameter("messageRate", 25, LiveObjects.INT); -lo.addParameter("sendDHTData", true ,LiveObjects.BINARY, myCallbackFunction); -... +lo.addParameter("messageRate", 25, LiveObjects.INT) +lo.addParameter("sendDHTData", true, LiveObjects.BINARY, myCallbackFunction) +# ... if lo.getParameter("sendDHTData"): - lo.addToPayload("temperature",DHT.readTemeprature()) - lo.addToPayload("humidity",DHT.readHumidity()) + lo.addToPayload("temperature", DHT.readTemeprature()) + lo.addToPayload("humidity", DHT.readHumidity()) ``` -The callback function takes 2 arguments +The callback function takes 2 arguments: ```Python def myCallbackFunction(parameterName, newValue): - // do stuff + # do stuff ``` Further reading on Live Objects' [Parameters](https://liveobjects.orange-business.com/doc/html/lo_manual.html#_configuration). ### Declare commands ### -Commands lets you trigger specific actions on your device from Live Objects. Parameters and Commands must be declared _before_ your device connects to Live Objects. +Commands let you trigger specific actions on your device from Live Objects. Parameters and Commands must be declared _before_ your device connects to Live Objects. Commands can be declared using the `addcommand()` instruction, which accepts the following arguments: - the label of your command @@ -92,29 +93,28 @@ Commands can be declared using the `addcommand()` instruction, which accepts the lo.addParameter("a command", myCallback); ``` -The callback function should take 1 parameter and return dictonary +The callback function should take 1 parameter and return dictionary: ```Python def myCallback(args={}): - // do stuff - return {} + # do stuff + return {} ``` Arguments and response are optional when using commands, but they can be useful if you want to pass parameters to your function. For instance, you could define a `play tone` command that will use some parameters like the frequency of the tone, or its duration. -- Any incoming arguments will be passed as member of a dictonary -- You can pass response arguments in the form of a dictonary by returning them +- Any incoming arguments will be passed as member of a dictionary +- You can pass response arguments in the form of a dictionary by returning them ```Python def playTone(args={}): - duration = args["duration"] - frequency = args["frequency"] - // play the tone accordingly to arguments - ... - return {"I played":"the tone"} -} + duration = args["duration"] + frequency = args["frequency"] + # play the tone accordingly to arguments + # ... + return {"I played": "the tone"} def setup(): - lo.addCommand("play tone", playTone) + lo.addCommand("play tone", playTone) ``` -> :warning: **Command name and arguments are case-sensitive when creating the command on Live Objects.**: On the opposite, there is no specific order for specifying the command arguments. +> Warning: **Command name and arguments are case-sensitive when creating the command on Live Objects.**: On the opposite, there is no specific order for specifying the command arguments. Further reading on Live Objects' [Commands](https://liveobjects.orange-business.com/doc/html/lo_manual.html#MQTT_DEV_CMD). @@ -122,34 +122,34 @@ Further reading on Live Objects' [Commands](https://liveobjects.orange-business. You can send data very easily to Live Objects. #### Dead simple method #### -Compose your payload using the `addToPayload()` instruction. You will need to provide a label for your value, and the data itself. You data can be of any simple type. +Compose your payload using the `addToPayload()` instruction. You will need to provide a label for your value, and the data itself. Your data can be of any simple type. Data is added on each call to `addToPayload()`, so repeat the instruction if you have multiple data to send. When your payload is ready, send it using `sendData()`. That simple. ```Python -value=21 -myOtherValue=37 +VALUE = 21 +MY_OTHER_VALUE = 37 def foo(): - // collect data - lo.addToPayload("my data", value) - lo.addToPayload("my other data", myOtherValue) - lo.sendData() # send to LiveObjects + # collect data + lo.addToPayload("my data", VALUE) + lo.addToPayload("my other data", MY_OTHER_VALUE) + lo.sendData() # send to LiveObjects ``` -As soon the data is send, your payload is cleared and waiting for the next sending. +As soon the data is sent, your payload is cleared and waiting for the next sending. -### Advanced payload feautres ### +### Advanced payload features ### ```Python - #add "model" property to your message - lo.addModel("exampleName") +# Add "model" property to your message +lo.addModel("exampleName") - #Add "tag" property to your message - lo.addTag("kitchen") - lo.addTags(["humidity","bathroom"]) +# Add "tag" property to your message +lo.addTag("kitchen") +lo.addTags(["humidity", "bathroom"]) - #Use your object as payload (this function doesn't append current paylod) - obj = ["example":"value", "example2":"value2" ] - lo.setObjectAsPayload(obj) +# Use your object as payload (this function doesn't append current payload) +obj = {"example":"value", "example2":"value2"} +lo.setObjectAsPayload(obj) ``` @@ -157,88 +157,70 @@ As soon the data is send, your payload is cleared and waiting for the next sendi You can control the connection and disconnection of your device using `connect()` and `disconnect()`. - In order to check for any incoming configuration update or command, you need to keep the `loop()` instruction in your main loop. ```Python def foo(): - lo.connect(); - while True: - #Do some stuff - #... - lo.loop(); #Keep this in main loop - lo.disconnect() + lo.connect(); + while True: + # Do some stuff + #... + lo.loop(); #Keep this in main loop + lo.disconnect() ``` # Installation guide for uPython # -## Example for ESP8266 ## -## Requirements ## +## Example for ESP32 / ESP8266 ## +### Requirements ### 1. [ampy](https://learn.adafruit.com/micropython-basics-load-files-and-run-code/install-ampy) 2. [umqttsimple, umqttrobust and ssl](https://github.com/micropython/micropython-lib) 3. [PuTTY](https://www.putty.org/) (for Windows) -## Installation steps ## -1. Copy files into device - ``` - ampy -pCOMXX put umqttrobus.py - ampy -pCOMXX put umqttsimple.py - ampy -pCOMXX put ssl.py - ampy -pCOMXX put LiveObjects //It will copy directory with its content - ``` -2. Prepare your sketch and save it as main.py then copy file into device -``` -ampy -pCOMXX put main.py -``` -3. Setup internet connection in boot.py file and upload it into device. -```Python -# This file is executed on every boot (including wake-boot from deepsleep) -#import esp -#esp.osdebug(None) -import uos, machine -#uos.dupterm(None, 1) # disable REPL on UART(0) -import gc -#import webrepl -#webrepl.start() -gc.collect() - - -#Network connection -import network -sta_if = network.WLAN(network.STA_IF) -if not sta_if.isconnected(): - print('connecting to network...') - sta_if.active(True) - sta_if.connect('SSID', 'PASS') - while not sta_if.isconnected(): - pass -print('network config:', sta_if.ifconfig()) -``` -You may want to get content of file first, then use +### Installation steps ### + +1. Preparation + +Change **\** in `credentials.py` to one you generated.\ +Change **\** and **\** suitable to your WiFi. + + +2. Copy files into device +```Shell +>ampy -pCOMXX put umqttrobust.py +>ampy -pCOMXX put simple.py +>ampy -pCOMXX put LiveObjects // It will copy directory with its content ``` -ampy -pCOMXX get boot.py +3. Prepare your script and save it as `main.py` then copy file into device. You can use one of example ones (`1_send_data.py`, ...) renaming it to `main.py` +```Shell +>ampy -pCOMXX put main.py ``` + 4. Connect to device and check if it's working using PuTTY - Crtl + D soft resets device - + Ctrl + D soft resets device + Ctrl + C Stops currently running script -## Summary ## -After all steps content of the device should look like this -``` +### Summary ### +After all steps content of the device should look like below: +```Shell >ampy -pCOMXX ls /LiveObjects /boot.py /main.py -/ssl.py /umqttrobust.py -/umqttsimple.py +/simple.py >ampy -pCOMXX ls LiveObjects /LiveObjects/Connection.py /LiveObjects/__init__.py -/LiveObjects/certfile.cer +/LiveObjects/hal.py +/LiveObjects/credentials.py ``` +## Example for LoPy / GPy ## + +You can do the steps as above but better is to use [Pymakr plug-in](https://pycom.io/products/supported-networks/pymakr/) for **Visual Studio Code** or **Atom** delivered by [Pycom](https://pycom.io/). Plug-in supports code development, its upload to board and communication with board. + ## Troubleshooting ## If you are getting 'MQTT exception: 5' check your api key \ No newline at end of file From a648e86443fd909c06ee6e3bf95b3c4669bf0080 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Wed, 23 Mar 2022 08:34:43 +0100 Subject: [PATCH 34/47] Removing unused method 'get_os_id'. --- LiveObjects/hal.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index d2d3c4a..e720b09 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -117,9 +117,6 @@ def connect(self): def get_security_level(self): return LiveObjects.SSL if self._existing_network_tls_capability else LiveObjects.NONE - def get_os_id(self): - return self._os_id - def get_store_cert_filename(self): try: import certifi @@ -161,9 +158,6 @@ def connect(self): def get_security_level(self): return LiveObjects.SSL if self._existing_network_tls_capability else LiveObjects.NONE - def get_os_id(self): - return self._os_id - def get_store_cert_filename(self): return self._cert_store_filename From a260d7af6f537b3f240288d217dd662860f0dadb Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Wed, 23 Mar 2022 11:08:45 +0100 Subject: [PATCH 35/47] Adding support for LoPy. --- LiveObjects/hal.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index e720b09..93a19b6 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -58,7 +58,23 @@ def network_disconnect(self): class LoPy(BoardsInterface): - pass + def __init__(self, net_type): + self._lang_id = BoardsInterface.MICROPYTHON + self._net_type = BoardsInterface.WIFI if net_type == BoardsInterface.DEFAULT_CARRIER else net_type + self._carrier_capability = (BoardsInterface.WIFI,) + self._wifi_tls_capability = False + self._credentials = super().create_credentials(self._net_type) + self._hostname = 'LoPy' + + def connect(self): + super().check_network_capabilities(self._net_type) + if self._net_type == BoardsInterface.WIFI: + pycom_wifi_connect(self._credentials.get_creds()['ssid'], self._credentials.get_creds()['password'], + self._hostname) + + def get_security_level(self): + if self._net_type == BoardsInterface.WIFI: + return LiveObjects.SSL if self._wifi_tls_capability else LiveObjects.NONE class GPy(BoardsInterface): From 1bb063fca20d405abea34794aa56f871cd8ae023 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Mon, 28 Mar 2022 11:47:45 +0200 Subject: [PATCH 36/47] README.md update. --- README.md | 87 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 72 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index ef72985..a08aaa0 100644 --- a/README.md +++ b/README.md @@ -3,21 +3,21 @@ This code wraps all the functions necessary to make your object work with Live Objects. - You can declare parameters, which you can later update OTA from Live objects. You can also create commands to trigger actions remotely. - Only thing you must do yourself is connecting the board with internet. +You can declare parameters, which you can later update OTA from Live objects. You can also create commands to trigger actions remotely. +Only thing you must do yourself is connecting the board with internet. Code uses MQTT connection to exchange data with Live objects under the hood to keep your parameters up to date or execute the commands received without you having to take care of them (apart from writing the code of these commands, of course). ## Compatibility ## -| System | Connectivity | MQTT | MQTTS | -|:--------------|-----------------|:----:|:-----:| -| Linux | Delivered by OS | OK | OK | -| Windows | Delivered by OS | OK | OK | -| Raspberry Pi | Delivered by OS | OK | OK | -| ESP8266 | WiFi | OK | - | -| ESP32 | WiFi | OK | OK | -| LoPy (Pycom) | WiFi | OK | - | -| GPy (Pycom) | WiFi, LTE | OK | - | +| System | MQTT | MQTTS | +|:--------------|:----:|:-----:| +| Linux | OK | OK | +| Windows | OK | OK | +| Raspberry Pi | OK | OK | +| ESP8266 | OK | - | +| ESP32 | OK | OK | +| LoPy (Pycom) | OK | - | +| GPy (Pycom) | OK | - | ## Prerequisites / dependecies ## This code needs a few libraries to run: @@ -168,6 +168,60 @@ def foo(): lo.disconnect() ``` +### Changing default carrier to connect to the network ### + +Every board has its own default carrier for connection to the network (see below). + +| System | Default carrier | Optional carrier | +|:--------------|:---------------:|:----------------:| +| Linux | Delivered by OS | - | +| Windows | Delivered by OS | - | +| Raspberry Pi | Delivered by OS | - | +| ESP8266 | Wi-Fi | - | +| ESP32 | Wi-Fi | - | +| LoPy (Pycom) | Wi-Fi | - | +| GPy (Pycom) | Wi-Fi | LTE | + +For GPy you can switch connectivity to optional carrier. You need to do change in `Connection` class in `Connection.py` +from: +```Python +def __init__(self, debug=True): + self.__board = LiveObjects.BoardsFactory(net_type=LiveObjects.BoardsInterface.DEFAULT_CARRIER) +... +``` +to: +```Python +def __init__(self, debug=True): + self.__board = LiveObjects.BoardsFactory(net_type=LiveObjects.BoardsInterface.LTE) +... +``` +Then GPy will connect via LTE network. + +### Adding new boards ### + +There is possibility to add your new type of board supporting Python/uPython. +You need to add your own class in `hal.py`. +Below code shows basic constructor: +```Python +def __init__(self, net_type): + self._lang_id = BoardsInterface.MICROPYTHON + self._net_type = BoardsInterface.WIFI if net_type == BoardsInterface.DEFAULT_CARRIER else net_type + self._carrier_capability = (BoardsInterface.WIFI,) + self._wifi_tls_capability = False + self._credentials = super().create_credentials(self._net_type) +``` +Basic fields meaning: +- **_lang_id**: used Python dialect: PYTHON / MICROPYTHON, +- **_net_type**: used type of network: WIFI / LTE / network delivered by OS / ... +- **_carrier_capability**: _tuple_ containing supported type(s) of network, +- **_wifi_tls_capability**: _True_ if TLS is supported and MQTTS could be used, +- **_credentials**: required credentials depended on network type: SSID/PASS for Wi-Fi, PIN/APN for LTE etc. + +If other specific fields are necessary you need to define them. +You need to override specific methods - e.g. `connect` which is depended on type of board. +All specific functions are placed at the end of `hal.py`. +If your board needs function supporting its equipment you need to put it in this place. + # Installation guide for uPython # ## Example for ESP32 / ESP8266 ## @@ -181,8 +235,8 @@ def foo(): 1. Preparation Change **\** in `credentials.py` to one you generated.\ -Change **\** and **\** suitable to your WiFi. - +Change **\** and **\** suitable to your Wi-Fi or +change **\** and **\** suitable to your SIM card. 2. Copy files into device ```Shell @@ -190,7 +244,8 @@ Change **\** and **\** suitable to your WiFi. >ampy -pCOMXX put simple.py >ampy -pCOMXX put LiveObjects // It will copy directory with its content ``` -3. Prepare your script and save it as `main.py` then copy file into device. You can use one of example ones (`1_send_data.py`, ...) renaming it to `main.py` +3. Prepare your script and save it as `main.py` then copy file into device. +You can use one of example ones (`1_send_data.py`, ...) renaming it to `main.py` ```Shell >ampy -pCOMXX put main.py ``` @@ -202,6 +257,7 @@ Change **\** and **\** suitable to your WiFi. Ctrl + C Stops currently running script ### Summary ### + After all steps content of the device should look like below: ```Shell >ampy -pCOMXX ls @@ -220,7 +276,8 @@ After all steps content of the device should look like below: ## Example for LoPy / GPy ## -You can do the steps as above but better is to use [Pymakr plug-in](https://pycom.io/products/supported-networks/pymakr/) for **Visual Studio Code** or **Atom** delivered by [Pycom](https://pycom.io/). Plug-in supports code development, its upload to board and communication with board. +You can do the steps as above but better is to use [Pymakr plug-in](https://pycom.io/products/supported-networks/pymakr/) for **Visual Studio Code** or **Atom** delivered by [Pycom](https://pycom.io/). +Plug-in supports code development, its upload to the board and communication with board. ## Troubleshooting ## If you are getting 'MQTT exception: 5' check your api key \ No newline at end of file From 12a56cb57d3a36e8c867afc878484ba0e8d6b730 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Mon, 28 Mar 2022 12:11:24 +0200 Subject: [PATCH 37/47] Removing old 'certfile.cer'. --- LiveObjects/certfile.cer | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 LiveObjects/certfile.cer diff --git a/LiveObjects/certfile.cer b/LiveObjects/certfile.cer deleted file mode 100644 index fd4341d..0000000 --- a/LiveObjects/certfile.cer +++ /dev/null @@ -1,22 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD -QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT -MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j -b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB -CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 -nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt -43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P -T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 -gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO -BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR -TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw -DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr -hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg -06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF -PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls -YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk -CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= ------END CERTIFICATE----- From b4ab859b995f4f4bdea3e4674dbf85dae546b71c Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Mon, 28 Mar 2022 13:39:39 +0200 Subject: [PATCH 38/47] Adding '' in 'credentials.py'. Small 'README.md' correction. --- LiveObjects/credentials.py | 10 +++++----- README.md | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/LiveObjects/credentials.py b/LiveObjects/credentials.py index 4bd2e61..8ec19e5 100644 --- a/LiveObjects/credentials.py +++ b/LiveObjects/credentials.py @@ -10,15 +10,15 @@ class Credentials: def __init__(self, net_type): - self._apikey = + self._apikey = '' self._net_type = net_type if net_type == LiveObjects.BoardsInterface.WIFI: - self._wifi_ssid = - self._wifi_password = + self._wifi_ssid = '' + self._wifi_password = '' elif net_type == LiveObjects.BoardsInterface.LTE: - self._pin = - self._apn = + self._pin = '' + self._apn = '' def get_apikey(self): return self._apikey diff --git a/README.md b/README.md index a08aaa0..ea78f45 100644 --- a/README.md +++ b/README.md @@ -236,7 +236,7 @@ If your board needs function supporting its equipment you need to put it in this Change **\** in `credentials.py` to one you generated.\ Change **\** and **\** suitable to your Wi-Fi or -change **\** and **\** suitable to your SIM card. +change **\** and **\** suitable to your SIM card. 2. Copy files into device ```Shell From 8095d310c8a4634b4d476115577729749db8a889 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Tue, 29 Mar 2022 09:50:26 +0200 Subject: [PATCH 39/47] Update 'setup.py' --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index c1dd677..14285a6 100644 --- a/setup.py +++ b/setup.py @@ -5,14 +5,14 @@ name='LiveObjects', url='https://github.com/DatavenueLiveObjects/LiveObjects_SDK_for_Python', - author='Kacper Sawicki, Krzysztof Krześlak', + author='Kacper Sawicki, Krzysztof Krześlak, Tomasz Malek', #author_email='', packages=['LiveObjects'], include_package_data=True, install_requires=['paho-mqtt'], - version='1.0.0', + version='2.0.0', license='MIT', From 05a782eaf09dbc4daa2cea5d635d347804ecfd81 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Wed, 30 Mar 2022 15:41:22 +0200 Subject: [PATCH 40/47] Update of 'get_client_id()' in hal.py in order to individualize client_id by adding MAC address for Linux and Windows. --- LiveObjects/hal.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index 93a19b6..4158d49 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -4,7 +4,6 @@ # This software is distributed under the terms and conditions of the 'MIT' # license which can be found in the file 'LICENSE.md' in this package distribution -import os import time import sys @@ -29,7 +28,7 @@ def get_apikey(self): return self._credentials.get_apikey() def get_client_id(self): - return self.get_lang_str() + 'MQTT' + pass def get_lang_str(self): lang_dict = {BoardsInterface.PYTHON: 'Python', @@ -76,6 +75,9 @@ def get_security_level(self): if self._net_type == BoardsInterface.WIFI: return LiveObjects.SSL if self._wifi_tls_capability else LiveObjects.NONE + def get_client_id(self): + return self.get_lang_str() + 'MQTT' + class GPy(BoardsInterface): def __init__(self, net_type): @@ -101,6 +103,8 @@ def get_security_level(self): elif self._net_type == BoardsInterface.LTE: return LiveObjects.SSL if self._lte_tls_capability else LiveObjects.NONE + def get_client_id(self): + return self.get_lang_str() + 'MQTT' class Esp8266(BoardsInterface): def __init__(self, net_type): @@ -117,6 +121,9 @@ def connect(self): def get_security_level(self): return LiveObjects.SSL if self._wifi_tls_capability else LiveObjects.NONE + def get_client_id(self): + return self.get_lang_str() + 'MQTT' + class Win32(BoardsInterface): def __init__(self, net_type): @@ -141,6 +148,10 @@ def get_store_cert_filename(self): print("[ERROR] U have missing library 'python-certifi-win32'") sys.exit() + def get_client_id(self): + import uuid + return self.get_lang_str() + 'MQTT_' + (''.join(['{:02x}'.format((uuid.getnode() >> ele) & 0xff) for ele in range(0,8*6,8)][::-1])) + class Esp32(BoardsInterface): def __init__(self, net_type): @@ -157,6 +168,9 @@ def connect(self): def get_security_level(self): return LiveObjects.SSL if self._wifi_tls_capability else LiveObjects.NONE + def get_client_id(self): + return self.get_lang_str() + 'MQTT' + class Linux(BoardsInterface): def __init__(self, net_type): @@ -177,6 +191,10 @@ def get_security_level(self): def get_store_cert_filename(self): return self._cert_store_filename + def get_client_id(self): + import uuid + return self.get_lang_str() + 'MQTT_' + (''.join(['{:02x}'.format((uuid.getnode() >> ele) & 0xff) for ele in range(0,8*6,8)][::-1])) + class BoardsFactory: From 0beda0b7a68e42648c36d51bb89c5169282f877c Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Thu, 31 Mar 2022 08:44:53 +0200 Subject: [PATCH 41/47] Adding info to section connected to creating class for your board. --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ea78f45..ecdfff3 100644 --- a/README.md +++ b/README.md @@ -200,7 +200,13 @@ Then GPy will connect via LTE network. ### Adding new boards ### There is possibility to add your new type of board supporting Python/uPython. -You need to add your own class in `hal.py`. +You need to add your own class in `hal.py`. Name of this class has to be the same as output of `sys.platform` +and has to start from capital letter. +```commandline +>>> sys.platform +'GPy' +>>> +``` Below code shows basic constructor: ```Python def __init__(self, net_type): From 546007b0520f1b25a26a7f2aa4a59fe1ea9e8338 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Thu, 31 Mar 2022 15:12:12 +0200 Subject: [PATCH 42/47] Update of 'get_client_id()' in hal.py in order to individualize client id for other boards. --- LiveObjects/hal.py | 45 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index 4158d49..da6ee68 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -76,7 +76,7 @@ def get_security_level(self): return LiveObjects.SSL if self._wifi_tls_capability else LiveObjects.NONE def get_client_id(self): - return self.get_lang_str() + 'MQTT' + return self.get_lang_str() + 'MQTT_' + get_pycom_mac() class GPy(BoardsInterface): @@ -104,7 +104,11 @@ def get_security_level(self): return LiveObjects.SSL if self._lte_tls_capability else LiveObjects.NONE def get_client_id(self): - return self.get_lang_str() + 'MQTT' + if self._net_type == BoardsInterface.WIFI: + return self.get_lang_str() + 'MQTT_' + get_pycom_mac() + elif self._net_type == BoardsInterface.LTE: + return self.get_lang_str() + 'MQTT_' + get_pycom_imei() + class Esp8266(BoardsInterface): def __init__(self, net_type): @@ -122,7 +126,7 @@ def get_security_level(self): return LiveObjects.SSL if self._wifi_tls_capability else LiveObjects.NONE def get_client_id(self): - return self.get_lang_str() + 'MQTT' + return self.get_lang_str() + 'MQTT_' + get_esp_mac() class Win32(BoardsInterface): @@ -149,8 +153,7 @@ def get_store_cert_filename(self): sys.exit() def get_client_id(self): - import uuid - return self.get_lang_str() + 'MQTT_' + (''.join(['{:02x}'.format((uuid.getnode() >> ele) & 0xff) for ele in range(0,8*6,8)][::-1])) + return self.get_lang_str() + 'MQTT_' + get_mac() class Esp32(BoardsInterface): @@ -169,7 +172,7 @@ def get_security_level(self): return LiveObjects.SSL if self._wifi_tls_capability else LiveObjects.NONE def get_client_id(self): - return self.get_lang_str() + 'MQTT' + return self.get_lang_str() + 'MQTT_' + get_esp_mac() class Linux(BoardsInterface): @@ -192,8 +195,7 @@ def get_store_cert_filename(self): return self._cert_store_filename def get_client_id(self): - import uuid - return self.get_lang_str() + 'MQTT_' + (''.join(['{:02x}'.format((uuid.getnode() >> ele) & 0xff) for ele in range(0,8*6,8)][::-1])) + return self.get_lang_str() + 'MQTT_' + get_mac() class BoardsFactory: @@ -209,10 +211,15 @@ def use_existing_network_connection(): print('Using existing network connection') +def get_mac(): + import uuid + return ''.join(['{:02x}'.format((uuid.getnode() >> ele) & 0xff) for ele in range(0, 8*6, 8)][::-1]).upper() + + def wifi_connect(ssid, password): - import network + from network import WLAN, STA_IF - sta_if = network.WLAN(network.STA_IF) + sta_if = WLAN(STA_IF) sta_if.active(True) while not sta_if.isconnected(): print('Connecting to network...') @@ -223,6 +230,12 @@ def wifi_connect(ssid, password): print('Network config:', sta_if.ifconfig()) +def get_esp_mac(): + from network import WLAN + import binascii + return binascii.hexlify(WLAN().config('mac')).decode('ascii').upper() + + CONN_TIMEOUT = 20 @@ -245,8 +258,13 @@ def pycom_wifi_connect(ssid, password, hostname): break -def lte_connect(pin): +def get_pycom_mac(): + from network import WLAN + import binascii + return binascii.hexlify(WLAN().mac()[0]).decode('ascii').upper() + +def lte_connect(pin): from network import LTE def is_sim_waiting_for_pin(): @@ -274,3 +292,8 @@ def is_sim_waiting_for_pin(): while not lte.isconnected(): time.sleep(1) print("connected!") + + +def get_pycom_imei(): + from network import LTE + return LTE().imei() From fbe0ff4ee92d101adfc73fea0bb162130c899b32 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Fri, 1 Apr 2022 15:54:44 +0200 Subject: [PATCH 43/47] Necessary refactoring due to lack of memory on ESP8266. Moving common functions to new module 'services.py'. --- LiveObjects/hal.py | 108 ++++++---------------------------------- LiveObjects/services.py | 98 ++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 93 deletions(-) create mode 100644 LiveObjects/services.py diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index da6ee68..be80873 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -4,7 +4,7 @@ # This software is distributed under the terms and conditions of the 'MIT' # license which can be found in the file 'LICENSE.md' in this package distribution -import time +# import time import sys import LiveObjects @@ -68,6 +68,7 @@ def __init__(self, net_type): def connect(self): super().check_network_capabilities(self._net_type) if self._net_type == BoardsInterface.WIFI: + from LiveObjects.services import pycom_wifi_connect pycom_wifi_connect(self._credentials.get_creds()['ssid'], self._credentials.get_creds()['password'], self._hostname) @@ -76,6 +77,7 @@ def get_security_level(self): return LiveObjects.SSL if self._wifi_tls_capability else LiveObjects.NONE def get_client_id(self): + from LiveObjects.services import get_pycom_mac return self.get_lang_str() + 'MQTT_' + get_pycom_mac() @@ -92,9 +94,11 @@ def __init__(self, net_type): def connect(self): super().check_network_capabilities(self._net_type) if self._net_type == BoardsInterface.WIFI: + from LiveObjects.services import pycom_wifi_connect pycom_wifi_connect(self._credentials.get_creds()['ssid'], self._credentials.get_creds()['password'], self._hostname) elif self._net_type == BoardsInterface.LTE: + from LiveObjects.services import lte_connect lte_connect(self._credentials.get_creds()['pin']) def get_security_level(self): @@ -105,8 +109,10 @@ def get_security_level(self): def get_client_id(self): if self._net_type == BoardsInterface.WIFI: + from LiveObjects.services import get_pycom_mac return self.get_lang_str() + 'MQTT_' + get_pycom_mac() elif self._net_type == BoardsInterface.LTE: + from LiveObjects.services import get_pycom_imei return self.get_lang_str() + 'MQTT_' + get_pycom_imei() @@ -119,6 +125,7 @@ def __init__(self, net_type): self._credentials = super().create_credentials(self._net_type) def connect(self): + from LiveObjects.services import wifi_connect super().check_network_capabilities(self._net_type) wifi_connect(self._credentials.get_creds()['ssid'], self._credentials.get_creds()['password']) @@ -126,6 +133,7 @@ def get_security_level(self): return LiveObjects.SSL if self._wifi_tls_capability else LiveObjects.NONE def get_client_id(self): + from LiveObjects.services import get_esp_mac return self.get_lang_str() + 'MQTT_' + get_esp_mac() @@ -138,6 +146,7 @@ def __init__(self, net_type): self._credentials = super().create_credentials(self._net_type) def connect(self): + from LiveObjects.services import use_existing_network_connection super().check_network_capabilities(self._net_type) use_existing_network_connection() @@ -153,6 +162,7 @@ def get_store_cert_filename(self): sys.exit() def get_client_id(self): + from LiveObjects.services import get_mac return self.get_lang_str() + 'MQTT_' + get_mac() @@ -165,6 +175,7 @@ def __init__(self, net_type): self._credentials = super().create_credentials(self._net_type) def connect(self): + from LiveObjects.services import wifi_connect super().check_network_capabilities(self._net_type) wifi_connect(self._credentials.get_creds()['ssid'], self._credentials.get_creds()['password']) @@ -172,6 +183,7 @@ def get_security_level(self): return LiveObjects.SSL if self._wifi_tls_capability else LiveObjects.NONE def get_client_id(self): + from LiveObjects.services import get_esp_mac return self.get_lang_str() + 'MQTT_' + get_esp_mac() @@ -185,6 +197,7 @@ def __init__(self, net_type): self._cert_store_filename = "/etc/ssl/certs/ca-certificates.crt" def connect(self): + from LiveObjects.services import use_existing_network_connection super().check_network_capabilities(self._net_type) use_existing_network_connection() @@ -195,6 +208,7 @@ def get_store_cert_filename(self): return self._cert_store_filename def get_client_id(self): + from LiveObjects.services import get_mac return self.get_lang_str() + 'MQTT_' + get_mac() @@ -205,95 +219,3 @@ def __new__(cls, net_type): sn = s[0].upper() + s[1:] # capitalize first letter board = eval(sn)(net_type) # instance of board w/ net type: WiFi, LTE, etc. return board - - -def use_existing_network_connection(): - print('Using existing network connection') - - -def get_mac(): - import uuid - return ''.join(['{:02x}'.format((uuid.getnode() >> ele) & 0xff) for ele in range(0, 8*6, 8)][::-1]).upper() - - -def wifi_connect(ssid, password): - from network import WLAN, STA_IF - - sta_if = WLAN(STA_IF) - sta_if.active(True) - while not sta_if.isconnected(): - print('Connecting to network...') - sta_if.connect(ssid, password) - if sta_if.isconnected(): - break - time.sleep(2) - print('Network config:', sta_if.ifconfig()) - - -def get_esp_mac(): - from network import WLAN - import binascii - return binascii.hexlify(WLAN().config('mac')).decode('ascii').upper() - - -CONN_TIMEOUT = 20 - - -def pycom_wifi_connect(ssid, password, hostname): - from network import WLAN - - wlan = WLAN(mode=WLAN.STA) - wlan.hostname(hostname) - start_time = time.time() - while 1: - print("Trying to connect...") - wlan.connect(ssid=ssid, auth=(WLAN.WPA2, password)) - time.sleep_ms(3000) - if wlan.isconnected(): - print("WiFi connected successfully") - print('IPs:', wlan.ifconfig(), 'Channel:', wlan.channel()) - break - elif time.time() - start_time > CONN_TIMEOUT: - print("WiFi not connected. Stopped.") - break - - -def get_pycom_mac(): - from network import WLAN - import binascii - return binascii.hexlify(WLAN().mac()[0]).decode('ascii').upper() - - -def lte_connect(pin): - from network import LTE - - def is_sim_waiting_for_pin(): - if lte.send_at_cmd('AT+CPIN?').strip() == '+CPIN: SIM PIN\r\n\r\nOK': - return True - else: - return False - - lte = LTE() - time.sleep(2) - - if is_sim_waiting_for_pin(): - print("PIN", (lte.send_at_cmd('AT+CPIN="%s"' % pin)).strip()) - else: - print("PIN PRESENT: OK") - - lte.attach() - print("Attaching... ", end='') - while not lte.isattached(): - time.sleep(1) - print("attached!") - - lte.connect() - print("Connecting... ", end='') - while not lte.isconnected(): - time.sleep(1) - print("connected!") - - -def get_pycom_imei(): - from network import LTE - return LTE().imei() diff --git a/LiveObjects/services.py b/LiveObjects/services.py new file mode 100644 index 0000000..4a0be4d --- /dev/null +++ b/LiveObjects/services.py @@ -0,0 +1,98 @@ +# +# Copyright (C) Orange +# +# This software is distributed under the terms and conditions of the 'MIT' +# license which can be found in the file 'LICENSE.md' in this package distribution + +import time + +def use_existing_network_connection(): + print('Using existing network connection') + + +def get_mac(): + import uuid + return ''.join(['{:02x}'.format((uuid.getnode() >> ele) & 0xff) for ele in range(0, 8*6, 8)][::-1]).upper() + + +def wifi_connect(ssid, password): + from network import WLAN, STA_IF + + sta_if = WLAN(STA_IF) + sta_if.active(True) + while not sta_if.isconnected(): + print('Connecting to network...') + sta_if.connect(ssid, password) + if sta_if.isconnected(): + break + time.sleep(2) + print('Network config:', sta_if.ifconfig()) + + +def get_esp_mac(): + from network import WLAN + import binascii + return binascii.hexlify(WLAN().config('mac')).decode('ascii').upper() + + +CONN_TIMEOUT = 20 + + +def pycom_wifi_connect(ssid, password, hostname): + from network import WLAN + + wlan = WLAN(mode=WLAN.STA) + wlan.hostname(hostname) + start_time = time.time() + while 1: + print("Trying to connect...") + wlan.connect(ssid=ssid, auth=(WLAN.WPA2, password)) + time.sleep_ms(3000) + if wlan.isconnected(): + print("WiFi connected successfully") + print('IPs:', wlan.ifconfig(), 'Channel:', wlan.channel()) + break + elif time.time() - start_time > CONN_TIMEOUT: + print("WiFi not connected. Stopped.") + break + + +def get_pycom_mac(): + from network import WLAN + import binascii + return binascii.hexlify(WLAN().mac()[0]).decode('ascii').upper() + + +def lte_connect(pin): + from network import LTE + + def is_sim_waiting_for_pin(): + if lte.send_at_cmd('AT+CPIN?').strip() == '+CPIN: SIM PIN\r\n\r\nOK': + return True + else: + return False + + lte = LTE() + time.sleep(2) + + if is_sim_waiting_for_pin(): + print("PIN", (lte.send_at_cmd('AT+CPIN="%s"' % pin)).strip()) + else: + print("PIN PRESENT: OK") + + lte.attach() + print("Attaching... ", end='') + while not lte.isattached(): + time.sleep(1) + print("attached!") + + lte.connect() + print("Connecting... ", end='') + while not lte.isconnected(): + time.sleep(1) + print("connected!") + + +def get_pycom_imei(): + from network import LTE + return LTE().imei() From 34535476c401ede6f56a90b8121b1dc2edc84cb3 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Mon, 4 Apr 2022 10:12:13 +0200 Subject: [PATCH 44/47] Editorial amendment. --- LiveObjects/services.py | 1 + README.md | 14 +++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/LiveObjects/services.py b/LiveObjects/services.py index 4a0be4d..a201c3c 100644 --- a/LiveObjects/services.py +++ b/LiveObjects/services.py @@ -6,6 +6,7 @@ import time + def use_existing_network_connection(): print('Using existing network connection') diff --git a/README.md b/README.md index ecdfff3..48e9a0b 100644 --- a/README.md +++ b/README.md @@ -225,8 +225,8 @@ Basic fields meaning: If other specific fields are necessary you need to define them. You need to override specific methods - e.g. `connect` which is depended on type of board. -All specific functions are placed at the end of `hal.py`. -If your board needs function supporting its equipment you need to put it in this place. +All specific functions are placed in `services.py`. +If your board needs function supporting its equipment you need to put it in this file. # Installation guide for uPython # @@ -246,9 +246,9 @@ change **\** and **\** suitable to your SIM card. 2. Copy files into device ```Shell ->ampy -pCOMXX put umqttrobust.py ->ampy -pCOMXX put simple.py ->ampy -pCOMXX put LiveObjects // It will copy directory with its content +> ampy -pCOMXX put umqttrobust.py +> ampy -pCOMXX put simple.py +> ampy -pCOMXX put LiveObjects // It will copy directory with its content ``` 3. Prepare your script and save it as `main.py` then copy file into device. You can use one of example ones (`1_send_data.py`, ...) renaming it to `main.py` @@ -266,14 +266,14 @@ You can use one of example ones (`1_send_data.py`, ...) renaming it to `main.py` After all steps content of the device should look like below: ```Shell ->ampy -pCOMXX ls +> ampy -pCOMXX ls /LiveObjects /boot.py /main.py /umqttrobust.py /simple.py ->ampy -pCOMXX ls LiveObjects +> ampy -pCOMXX ls LiveObjects /LiveObjects/Connection.py /LiveObjects/__init__.py /LiveObjects/hal.py From 03445fabd96474c17a48770a9591cc259d87a1f1 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Mon, 4 Apr 2022 13:16:10 +0200 Subject: [PATCH 45/47] Refactoring Connection.py to be according to PEP. --- 1_send_data.py | 4 +- 2_simple_parameters.py | 8 +-- 3_parameter_with_callback.py | 12 ++-- 4_simple_command.py | 8 +-- 5_command_with_arguments.py | 10 +-- LiveObjects/Connection.py | 123 +++++++++++++++++------------------ README.md | 57 +++++++++------- 7 files changed, 114 insertions(+), 108 deletions(-) diff --git a/1_send_data.py b/1_send_data.py index 36b1106..6ea86ca 100644 --- a/1_send_data.py +++ b/1_send_data.py @@ -18,7 +18,7 @@ while True: if (time.time()) >= last + MESSAGE_RATE: - lo.addToPayload("uptime", int(time.time() - uptime)) # Add value to payload: name - value - lo.sendData() # Sending data to cloud + lo.add_to_payload("uptime", int(time.time() - uptime)) # Add value to payload: name - value + lo.send_data() # Sending data to cloud last = time.time() lo.loop() # Check for incoming messages and if connection is still active diff --git a/2_simple_parameters.py b/2_simple_parameters.py index b89237c..82dc716 100644 --- a/2_simple_parameters.py +++ b/2_simple_parameters.py @@ -12,14 +12,14 @@ # Main program # Available types: INT, BINARY, STRING, FLOAT -lo.addParameter("messageRate", 5, LiveObjects.INT) # Add parameter: Name - Value - Type +lo.add_parameter("message_rate", 5, LiveObjects.INT) # Add parameter: Name - Value - Type lo.connect() # Connect to LiveObjects last = uptime = time.time() while True: - if time.time() >= last + lo.getParameter("messageRate"): # Get the parameter using its name - lo.addToPayload("uptime", int(time.time() - uptime)) # Add value to payload: name - value - lo.sendData() # Sending data to cloud + if time.time() >= last + lo.get_parameter("message_rate"): # Get the parameter using its name + lo.add_to_payload("uptime", int(time.time() - uptime)) # Add value to payload: name - value + lo.send_data() # Sending data to cloud last = time.time() lo.loop() # Check for incoming messages and if connection is still active diff --git a/3_parameter_with_callback.py b/3_parameter_with_callback.py index 00fc58f..3dd257e 100644 --- a/3_parameter_with_callback.py +++ b/3_parameter_with_callback.py @@ -14,19 +14,19 @@ # Callback for a parameter change -def callback(parameterName, newValue): - print("Changed value of the parameter " + parameterName + " to " + str(newValue)) +def callback(parameter_name, new_value): + print("Changed value of the parameter " + parameter_name + " to " + str(new_value)) # Main program # Available types: INT, BINARY, STRING, FLOAT -lo.addParameter("messageRate", 5, LiveObjects.INT, callback) # Add parameter: Name - Value - Type - Callback +lo.add_parameter("message_rate", 5, LiveObjects.INT, callback) # Add parameter: Name - Value - Type - Callback lo.connect() # Connect to LiveObjects last = uptime = time.time() while True: - if time.time() >= last + lo.getParameter("messageRate"): # Get the parameter using its name - lo.addToPayload("uptime", int(time.time() - uptime)) # Add value to payload: name - value - lo.sendData() # Sending data to cloud + if time.time() >= last + lo.get_parameter("message_rate"): # Get the parameter using its name + lo.add_to_payload("uptime", int(time.time() - uptime)) # Add value to payload: name - value + lo.send_data() # Sending data to cloud last = time.time() lo.loop() # Check for incoming messages and if connection is still active diff --git a/4_simple_command.py b/4_simple_command.py index 04a77e0..4003bb2 100644 --- a/4_simple_command.py +++ b/4_simple_command.py @@ -15,18 +15,18 @@ # Define command function def foo(arg={}): - lo.outputDebug(LiveObjects.INFO, "Called function foo") + lo.output_debug(LiveObjects.INFO, "Called function foo") return {} # Main program -lo.addCommand("foo", foo) # Add command to LiveObjects: name - function +lo.add_command("foo", foo) # Add command to LiveObjects: name - function lo.connect() # Connect to LiveObjects last = uptime = time.time() while True: if time.time() >= last + MESSAGE_RATE: - lo.addToPayload("uptime", int(time.time() - uptime)) # Add value to payload: name - value - lo.sendData() # Sending data to cloud + lo.add_to_payload("uptime", int(time.time() - uptime)) # Add value to payload: name - value + lo.send_data() # Sending data to cloud last = time.time() lo.loop() # Check for incoming messages and if connection is still active diff --git a/5_command_with_arguments.py b/5_command_with_arguments.py index c6f93e9..2b88d4c 100644 --- a/5_command_with_arguments.py +++ b/5_command_with_arguments.py @@ -16,22 +16,22 @@ # Define command function with arguments handling def foo(args={}): - lo.outputDebug(LiveObjects.INFO, "Called function foo with args", json.dumps(args)) + lo.output_debug(LiveObjects.INFO, "Called function foo with args", json.dumps(args)) counter = 0 for i in range(args["repetitions"]): print("Repetition nr " + str(i)) counter += 1 - return {"Repeated": str(counter) + " times"} + return {"Repeated": str(counter) + " times."} # Main program -lo.addCommand("foo", foo) # Add command to LiveObjects: name - function +lo.add_command("foo", foo) # Add command to LiveObjects: name - function lo.connect() # Connect to LiveObjects last = uptime = time.time() while True: if time.time() >= last + MESSAGE_RATE: - lo.addToPayload("uptime", int(time.time() - uptime)) # Add value to payload: name - value - lo.sendData() # Sending data to cloud + lo.add_to_payload("uptime", int(time.time() - uptime)) # Add value to payload: name - value + lo.send_data() # Sending data to cloud last = time.time() lo.loop() # Check for incoming messages and if connection is still active diff --git a/LiveObjects/Connection.py b/LiveObjects/Connection.py index 3e33515..e789bfa 100644 --- a/LiveObjects/Connection.py +++ b/LiveObjects/Connection.py @@ -62,114 +62,111 @@ def __init__(self, debug=True): elif self.mode == LiveObjects.BoardsInterface.MICROPYTHON: self.ssl = self.__port == SSL self.__mqtt = MQTTClient(self.__device_id, self.__server, self.__port, "json+device", - self.__apiKey, 0, self.ssl, {'server_hostname': self.__server}) + self.__apiKey, 0, self.ssl, {'server_hostname': self.__server}) def loop(self): if self.mode == LiveObjects.BoardsInterface.MICROPYTHON: self.__mqtt.check_msg() - def __onMessage(self, client="", userdata="", msg=""): + def __on_message(self, client="", userdata="", msg=""): if self.mode == LiveObjects.BoardsInterface.PYTHON: if msg.topic == "dev/cfg/upd": - self.__parameterManager(msg) + self.__parameter_manager(msg) elif msg.topic == "dev/cmd": - self.__commandManager(msg) + self.__command_manager(msg) elif self.mode == LiveObjects.BoardsInterface.MICROPYTHON: if client == b"dev/cfg/upd": - self.__parameterManager(userdata) + self.__parameter_manager(userdata) elif client == b"dev/cmd": - self.__commandManager(userdata) + self.__command_manager(userdata) - def __onConnect(self, client="", userdata="", flags="", rc=""): + def __on_connect(self, client="", userdata="", flags="", rc=""): if self.mode == LiveObjects.BoardsInterface.PYTHON: if rc == 0: - self.outputDebug(INFO, "Connected!") + self.output_debug(INFO, "Connected!") if len(self.__commands) > 0: - self.outputDebug(INFO, "Subscribing commands") + self.output_debug(INFO, "Subscribing commands") self.__mqtt.subscribe("dev/cmd") if len(self.__parameters) > 0: - self.outputDebug(INFO, "Subscribing parameters") + self.output_debug(INFO, "Subscribing parameters") self.__mqtt.subscribe("dev/cfg/upd") - self.__sendConfig() + self.__send_config() else: - self.outputDebug(ERROR, "Check your api key") - self.quit=True + self.output_debug(ERROR, "Check your api key") + self.quit = True sys.exit() - #else: - #self.outputDebug(ERROR,"Unknown error while connecting,quitting...") - #sys.exit() elif self.mode == LiveObjects.BoardsInterface.MICROPYTHON: - self.outputDebug(INFO, "Connected, sending config") + self.output_debug(INFO, "Connected, sending config") if len(self.__commands) > 0: - self.outputDebug(INFO, "Subscribing commands") + self.output_debug(INFO, "Subscribing commands") self.__mqtt.subscribe(b"dev/cmd") if len(self.__parameters) > 0: - self.outputDebug(INFO, "Subscribing parameters") + self.output_debug(INFO, "Subscribing parameters") self.__mqtt.subscribe(b"dev/cfg/upd") - self.__sendConfig() + self.__send_config() def connect(self): self.__board.connect() if self.mode == LiveObjects.BoardsInterface.PYTHON: self.__mqtt.username_pw_set("json+device", self.__apiKey) - self.__mqtt.on_connect = self.__onConnect - self.__mqtt.on_message = self.__onMessage + self.__mqtt.on_connect = self.__on_connect + self.__mqtt.on_message = self.__on_message if self.__port == SSL: self.__mqtt.tls_set(self.__board.get_store_cert_filename()) self.__mqtt.connect(self.__server, self.__port, 60) self.__mqtt.loop_start() elif self.mode == LiveObjects.BoardsInterface.MICROPYTHON: - self.__mqtt.set_callback(self.__onMessage) + self.__mqtt.set_callback(self.__on_message) self.__mqtt.connect() time.sleep(1) - self.__onConnect() + self.__on_connect() def disconnect(self): self.__mqtt.disconnect() - self.outputDebug(INFO, "Disconnected") + self.output_debug(INFO, "Disconnected") - def outputDebug(self, info, *args): + def output_debug(self, info, *args): if self.__doLog: print("[", info, "]", end=" ", sep="") for arg in args: print(arg, end=" ") print("") - def addCommand(self, name, cmd): + def add_command(self, name, cmd): self.__commands[name] = cmd - def __commandManager(self, msg): + def __command_manager(self, msg): if self.mode == LiveObjects.BoardsInterface.PYTHON: - msgDict = json.loads(msg.payload) - self.outputDebug(INFO, "Received message:\n", json.dumps(msgDict, sort_keys=True, indent=4)) + msg_dict = json.loads(msg.payload) + self.output_debug(INFO, "Received message:\n", json.dumps(msg_dict, sort_keys=True, indent=4)) elif self.mode == LiveObjects.BoardsInterface.MICROPYTHON: - msgDict = json.loads(msg) - self.outputDebug(INFO, "Received message:", json.dumps(msgDict)) - outputMsg = {} - outputMsg["cid"] = msgDict["cid"] - response = self.__commands.get(msgDict["req"], self.__default)(msgDict["arg"]) + msg_dict = json.loads(msg) + self.output_debug(INFO, "Received message:", json.dumps(msg_dict)) + output_msg = {} + output_msg["cid"] = msg_dict["cid"] + response = self.__commands.get(msg_dict["req"], self.__default)(msg_dict["arg"]) if len(response) > 0: - outputMsg["res"] = response - self.__publishMessage("dev/cmd/res", outputMsg) + output_msg["res"] = response + self.__publish_message("dev/cmd/res", output_msg) def __default(self, req=""): - self.outputDebug(INFO, "Command not found!") + self.output_debug(INFO, "Command not found!") return {"info": "Command not found"} - def __sendConfig(self): - outMsg = {"cfg": {}} + def __send_config(self): + out_msg = {"cfg": {}} for param in self.__parameters: - outMsg["cfg"][param] = {"t": self.__parameters[param].type, "v": self.__parameters[param].value} - self.__publishMessage("dev/cfg", outMsg) + out_msg["cfg"][param] = {"t": self.__parameters[param].type, "v": self.__parameters[param].value} + self.__publish_message("dev/cfg", out_msg) - def __parameterManager(self, msg): + def __parameter_manager(self, msg): if self.mode == LiveObjects.BoardsInterface.PYTHON: - self.outputDebug(INFO, "Received message: ") - self.outputDebug(INFO, json.loads(msg.payload)) + self.output_debug(INFO, "Received message: ") + self.output_debug(INFO, json.loads(msg.payload)) params = json.loads(msg.payload) elif self.mode == LiveObjects.BoardsInterface.MICROPYTHON: - self.outputDebug(INFO, "Received message: ") - self.outputDebug(INFO, json.loads(msg)) + self.output_debug(INFO, "Received message: ") + self.output_debug(INFO, json.loads(msg)) params = json.loads(msg) for param in params["cfg"]: @@ -187,9 +184,9 @@ def __parameterManager(self, msg): self.__parameters[param].value = params["cfg"][param]["v"] if self.__parameters[param].callback is not None: self.__parameters[param].callback(param, params["cfg"][param]["v"]) - self.__publishMessage("dev/cfg", params) + self.__publish_message("dev/cfg", params) - def addParameter(self, name, val, type_, cb=None): + def add_parameter(self, name, val, type_, cb=None): if type_ == INT: val = int(val) elif type_ == STRING: @@ -202,7 +199,7 @@ def addParameter(self, name, val, type_, cb=None): val = float(val) self.__parameters[name] = LiveObjectsParameter(val, type_, cb) - def getParameter(self, name): + def get_parameter(self, name): if self.__parameters[name].type == INT: return int(self.__parameters[name].value) elif self.__parameters[name].type == STRING: @@ -215,39 +212,39 @@ def getParameter(self, name): return float(self.__parameters[name].value) return 0 - def addToPayload(self, name, val): + def add_to_payload(self, name, val): self.__payload[self.__value][name] = val - def setObjectAsPayload(self, val): + def set_object_as_payload(self, val): self.__payload[self.__value] = val - def addModel(self, model): + def add_model(self, model): self.__payload["model"] = model - def addTag(self, tag): - if not "tags" in self.__payload: + def add_tag(self, tag): + if "tags" not in self.__payload: self.__payload["tags"] = [] self.__payload["tags"].append(tag) - def addTags(self, tags): - if not "tags" in self.__payload: + def add_tags(self, tags): + if "tags" not in self.__payload: self.__payload["tags"] = [] for tag in tags: self.__payload["tags"].append(tag) - def sendData(self): + def send_data(self): if self.quit: sys.exit() - self.__publishMessage("dev/data", self.__payload) + self.__publish_message("dev/data", self.__payload) self.__payload = {} self.__payload[self.__value] = {} - def __publishMessage(self, topic, msg): - self.outputDebug(INFO, "Publishing message on topic: ", topic) + def __publish_message(self, topic, msg): + self.output_debug(INFO, "Publishing message on topic: ", topic) if self.mode == LiveObjects.BoardsInterface.PYTHON: - self.outputDebug(INFO, "\n", json.dumps(msg, sort_keys=True, indent=4)) + self.output_debug(INFO, "\n", json.dumps(msg, sort_keys=True, indent=4)) elif self.mode == LiveObjects.BoardsInterface.MICROPYTHON: - self.outputDebug(INFO, json.dumps(msg)) + self.output_debug(INFO, json.dumps(msg)) self.__mqtt.publish(topic, json.dumps(msg)) diff --git a/README.md b/README.md index 48e9a0b..a5d9785 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Code uses MQTT connection to exchange data with Live objects under the hood to k | LoPy (Pycom) | OK | - | | GPy (Pycom) | OK | - | -## Prerequisites / dependecies ## +## Prerequisites / dependencies ## This code needs a few libraries to run: - Python needs [paho-mqtt](https://pypi.org/project/paho-mqtt/) - Python for Windows needs [python-certifi-win32](https://pypi.org/project/python-certifi-win32/) @@ -29,7 +29,7 @@ This code needs a few libraries to run: 1. Log in to [Live Objects](https://liveobjects.orange-business.com) or request a [trial account](https://liveobjects.orange-business.com/#/request_account) (up to 10 devices for 1 year) if you don't have one, 2. Create an [API key](https://liveobjects.orange-business.com/#/administration/apikeys) for your device. Give it a name, select the *Device access* role and validate. Copy the key, -3. Clone or download the directory from Github, +3. Clone or download the directory from GitHub, 4. Change **\** in `credentials.py` to one you generated, 5. Run selected `.py` script @@ -46,10 +46,11 @@ lo = LiveObjects.Connection() ### Debug messages ### You can use LiveObjects to output debug messages. + ```Python VALUE = 21 # INFO / ERROR / WARNING -lo.outputDebug(LiveObjects.INFO, "example value", VALUE, ...) +lo.output_debug(LiveObjects.INFO, "example value", VALUE, ...) # Output: [INFO] example value 21 ... ``` @@ -66,18 +67,19 @@ To retrieve a parameter use function `getParameter()` which takes following argu - Parameter name Example: + ```Python -lo.addParameter("messageRate", 25, LiveObjects.INT) -lo.addParameter("sendDHTData", true, LiveObjects.BINARY, myCallbackFunction) +lo.add_parameter("message_rate", 25, LiveObjects.INT) +lo.add_parameter("send_DHT_data", true, LiveObjects.BINARY, my_callback_function) # ... -if lo.getParameter("sendDHTData"): - lo.addToPayload("temperature", DHT.readTemeprature()) - lo.addToPayload("humidity", DHT.readHumidity()) +if lo.get_parameter("send_DHT_data"): + lo.add_to_payload("temperature", DHT.read_temeprature()) + lo.add_to_payload("humidity", DHT.read_humidity()) ``` The callback function takes 2 arguments: ```Python -def myCallbackFunction(parameterName, newValue): +def my_callback_function(parameter_name, new_value): # do stuff ``` @@ -89,13 +91,14 @@ Commands let you trigger specific actions on your device from Live Objects. Para Commands can be declared using the `addcommand()` instruction, which accepts the following arguments: - the label of your command - the callback function that will execute the command. + ```Python -lo.addParameter("a command", myCallback); +lo.add_parameter("a command", my_callback, ); ``` The callback function should take 1 parameter and return dictionary: ```Python -def myCallback(args={}): +def my_callback(args={}): # do stuff return {} ``` @@ -103,16 +106,18 @@ def myCallback(args={}): Arguments and response are optional when using commands, but they can be useful if you want to pass parameters to your function. For instance, you could define a `play tone` command that will use some parameters like the frequency of the tone, or its duration. - Any incoming arguments will be passed as member of a dictionary - You can pass response arguments in the form of a dictionary by returning them + ```Python -def playTone(args={}): +def play_tone(args={}): duration = args["duration"] frequency = args["frequency"] # play the tone accordingly to arguments # ... return {"I played": "the tone"} + def setup(): - lo.addCommand("play tone", playTone) + lo.add_command("play tone", play_tone) ``` > Warning: **Command name and arguments are case-sensitive when creating the command on Live Objects.**: On the opposite, there is no specific order for specifying the command arguments. @@ -125,31 +130,34 @@ You can send data very easily to Live Objects. Compose your payload using the `addToPayload()` instruction. You will need to provide a label for your value, and the data itself. Your data can be of any simple type. Data is added on each call to `addToPayload()`, so repeat the instruction if you have multiple data to send. When your payload is ready, send it using `sendData()`. That simple. + ```Python VALUE = 21 MY_OTHER_VALUE = 37 + def foo(): # collect data - lo.addToPayload("my data", VALUE) - lo.addToPayload("my other data", MY_OTHER_VALUE) - lo.sendData() # send to LiveObjects + lo.add_to_payload("my data", VALUE) + lo.add_to_payload("my other data", MY_OTHER_VALUE) + lo.send_data() # send to LiveObjects ``` As soon the data is sent, your payload is cleared and waiting for the next sending. ### Advanced payload features ### + ```Python # Add "model" property to your message -lo.addModel("exampleName") +lo.add_model("example_name") # Add "tag" property to your message -lo.addTag("kitchen") -lo.addTags(["humidity", "bathroom"]) +lo.add_tag("kitchen") +lo.add_tags(["humidity", "bathroom"]) # Use your object as payload (this function doesn't append current payload) -obj = {"example":"value", "example2":"value2"} -lo.setObjectAsPayload(obj) +obj = {"example": "value", "example2": "value2"} +lo.set_object_as_payload(obj) ``` @@ -245,7 +253,7 @@ Change **\** and **\** suitable to your Wi-Fi or change **\** and **\** suitable to your SIM card. 2. Copy files into device -```Shell +```commandline > ampy -pCOMXX put umqttrobust.py > ampy -pCOMXX put simple.py > ampy -pCOMXX put LiveObjects // It will copy directory with its content @@ -253,7 +261,7 @@ change **\** and **\** suitable to your SIM card. 3. Prepare your script and save it as `main.py` then copy file into device. You can use one of example ones (`1_send_data.py`, ...) renaming it to `main.py` ```Shell ->ampy -pCOMXX put main.py +> ampy -pCOMXX put main.py ``` 4. Connect to device and check if it's working using PuTTY @@ -265,7 +273,7 @@ You can use one of example ones (`1_send_data.py`, ...) renaming it to `main.py` ### Summary ### After all steps content of the device should look like below: -```Shell +```commandline > ampy -pCOMXX ls /LiveObjects /boot.py @@ -278,6 +286,7 @@ After all steps content of the device should look like below: /LiveObjects/__init__.py /LiveObjects/hal.py /LiveObjects/credentials.py +/LiveObjects/services.py ``` ## Example for LoPy / GPy ## From a60edf97823c50b66ebcc4afbb57cba3fb500d14 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Mon, 4 Apr 2022 14:49:11 +0200 Subject: [PATCH 46/47] Refactoring of Wi-Fi connectivity for ESPx and Pycom boards. --- LiveObjects/services.py | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/LiveObjects/services.py b/LiveObjects/services.py index a201c3c..95d5913 100644 --- a/LiveObjects/services.py +++ b/LiveObjects/services.py @@ -5,6 +5,7 @@ # license which can be found in the file 'LICENSE.md' in this package distribution import time +import sys def use_existing_network_connection(): @@ -16,18 +17,30 @@ def get_mac(): return ''.join(['{:02x}'.format((uuid.getnode() >> ele) & 0xff) for ele in range(0, 8*6, 8)][::-1]).upper() +CONN_TIMEOUT = 20 + + def wifi_connect(ssid, password): from network import WLAN, STA_IF sta_if = WLAN(STA_IF) sta_if.active(True) - while not sta_if.isconnected(): + start_time = time.time() + while True: print('Connecting to network...') - sta_if.connect(ssid, password) - if sta_if.isconnected(): - break - time.sleep(2) - print('Network config:', sta_if.ifconfig()) + try: + sta_if.connect(ssid, password) + time.sleep_ms(3000) + if sta_if.isconnected(): + print("WiFi connected successfully.") + print('Network config:', sta_if.ifconfig()) + break + elif time.time() - start_time > CONN_TIMEOUT: + print("[ERROR] Wi-Fi not connected. Stopped.") + sys.exit() + except OSError: + print("[ERROR] Wi-Fi not connected. Stopped.") + sys.exit() def get_esp_mac(): @@ -36,26 +49,23 @@ def get_esp_mac(): return binascii.hexlify(WLAN().config('mac')).decode('ascii').upper() -CONN_TIMEOUT = 20 - - def pycom_wifi_connect(ssid, password, hostname): from network import WLAN wlan = WLAN(mode=WLAN.STA) wlan.hostname(hostname) start_time = time.time() - while 1: + while True: print("Trying to connect...") wlan.connect(ssid=ssid, auth=(WLAN.WPA2, password)) time.sleep_ms(3000) if wlan.isconnected(): - print("WiFi connected successfully") + print("WiFi connected successfully.") print('IPs:', wlan.ifconfig(), 'Channel:', wlan.channel()) break elif time.time() - start_time > CONN_TIMEOUT: - print("WiFi not connected. Stopped.") - break + print("[ERROR] Wi-Fi not connected. Stopped.") + sys.exit() def get_pycom_mac(): From 021df4f5b097d8bf9a79252735e4d0fffcce7d77 Mon Sep 17 00:00:00 2001 From: Tomasz Malek Date: Mon, 4 Apr 2022 16:06:46 +0200 Subject: [PATCH 47/47] Editorial amendment. --- 3_parameter_with_callback.py | 1 - LiveObjects/Connection.py | 1 - LiveObjects/hal.py | 2 -- 3 files changed, 4 deletions(-) diff --git a/3_parameter_with_callback.py b/3_parameter_with_callback.py index 3dd257e..09865f6 100644 --- a/3_parameter_with_callback.py +++ b/3_parameter_with_callback.py @@ -4,7 +4,6 @@ # This software is distributed under the terms and conditions of the 'MIT' # license which can be found in the file 'LICENSE.md' in this package distribution - import time import LiveObjects diff --git a/LiveObjects/Connection.py b/LiveObjects/Connection.py index e789bfa..0efa679 100644 --- a/LiveObjects/Connection.py +++ b/LiveObjects/Connection.py @@ -7,7 +7,6 @@ import sys import json import time - import LiveObjects INT = "i32" diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py index be80873..8bcdfde 100644 --- a/LiveObjects/hal.py +++ b/LiveObjects/hal.py @@ -4,9 +4,7 @@ # This software is distributed under the terms and conditions of the 'MIT' # license which can be found in the file 'LICENSE.md' in this package distribution -# import time import sys - import LiveObjects