feat: sensor readings with JWT auth, OLED display, data_destination_url

This commit is contained in:
2026-06-09 13:20:10 +02:00
parent d1a28d989c
commit a25bbf0eb3
4 changed files with 137 additions and 13 deletions

View File

@@ -5,16 +5,140 @@
# ============================================================+
import utime
import ujson
import machine
try:
import uurequests as requests
except ImportError:
import urequests as requests
from identity_iot_aes import aes_cbc_encrypt, aes_cbc_decrypt
def run_sensor(cfg, caps):
"""Main loop for sensor node type. Called from boot_manager."""
print('[sensor] starting — sensor:', caps.get('has_sensor'))
def _read_internal_temp():
sensor = machine.ADC(4)
reading = sensor.read_u16()
voltage = reading * 3.3 / 65535
temp_c = 27 - (voltage - 0.706) / 0.001721
return round(temp_c, 2)
# TODO: read DHT22 / other sensor
# TODO: POST readings to backend via AES channel
# TODO: polling interval from cfg
def _read_dht22(dht_sensor):
try:
dht_sensor.measure()
return {
'temperature': dht_sensor.temperature(),
'humidity': dht_sensor.humidity(),
}
except Exception as e:
print('[sensor] DHT22 read error:', e)
return None
def _show_reading(reading, label):
try:
import boot_manager
temp = reading.get('temperature', reading.get('temp_internal', '--'))
hum = reading.get('humidity')
boot_manager._show([
'Identity IoT',
label or 'sensor',
'Temp: ' + str(temp) + 'C',
'Hum: ' + (str(hum) + '%' if hum is not None else '--'),
'',
])
except Exception as e:
print('[sensor] display error:', e)
def _post_reading(cfg, key, iv, payload, jwt_token=''):
url = cfg.get('data_destination_url', '')
if not url:
print('[sensor] no data_destination_url configured')
return False
try:
body = ujson.dumps({'data': aes_cbc_encrypt(ujson.dumps(payload), key, iv)})
resp = requests.post(
url,
headers={
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + jwt_token,
},
data=body,
timeout=10,
)
raw = resp.text
resp.close()
outer = ujson.loads(raw)
clear = aes_cbc_decrypt(outer['data'], key, iv)
result = ujson.loads(clear)
if result.get('status') == 'ok':
print('[sensor] reading posted ok')
return True
print('[sensor] post error:', result.get('code', 'unknown'))
return False
except Exception as e:
print('[sensor] post failed:', e)
return False
def run_sensor(cfg, caps, jwt_token=''):
print('[sensor] starting — has_sensor:', caps.get('has_sensor'))
key = cfg['comm_key'].encode() if isinstance(cfg['comm_key'], str) else cfg['comm_key']
iv = cfg['comm_iv'].encode() if isinstance(cfg['comm_iv'], str) else cfg['comm_iv']
poll_interval = int(cfg.get('poll_interval', 60))
temp_min = cfg.get('temp_min')
temp_max = cfg.get('temp_max')
node_id = cfg.get('node_id', '')
tenant_id = cfg.get('tenant_id', '')
label = cfg.get('node_label', '')
dht_sensor = None
if caps.get('has_sensor'):
try:
import dht
from machine import Pin
dht_pin = cfg.get('pinout', {}).get('dht_pin', 15)
dht_sensor = dht.DHT22(Pin(dht_pin))
except Exception as e:
print('[sensor] DHT22 init error:', e)
while True:
print('[sensor] polling...')
utime.sleep(10)
reading = {}
reading['temp_internal'] = _read_internal_temp()
if dht_sensor:
dht_data = _read_dht22(dht_sensor)
if dht_data:
reading['temperature'] = dht_data['temperature']
reading['humidity'] = dht_data['humidity']
print('[sensor] reading:', reading)
_show_reading(reading, label)
should_post = True
if temp_min is not None or temp_max is not None:
temp = reading.get('temperature', reading.get('temp_internal'))
in_range = True
if temp_min is not None and temp < float(temp_min):
in_range = False
if temp_max is not None and temp > float(temp_max):
in_range = False
if in_range:
should_post = False
if should_post:
payload = {
'request': 'iot_node_reading',
'node_id': node_id,
'tenant_id': tenant_id,
'label': label,
'reading': reading,
'ts': utime.time(),
}
_post_reading(cfg, key, iv, payload, jwt_token)
utime.sleep(poll_interval)