fix: fresh node_uid on re-registration, remove duplicate ensure_registered call
This commit is contained in:
@@ -129,7 +129,7 @@ def connect_wifi(cfg, timeout=30):
|
||||
_show_state('WIFI_CONNECT', cfg['wifi_ssid'])
|
||||
wlan = network.WLAN(network.STA_IF)
|
||||
wlan.active(True)
|
||||
utime.sleep(1)
|
||||
utime.sleep(2)
|
||||
|
||||
if not wlan.isconnected():
|
||||
wlan.connect(cfg['wifi_ssid'], cfg['wifi_pass'])
|
||||
@@ -155,7 +155,7 @@ def connect_wifi(cfg, timeout=30):
|
||||
ip = wlan.ifconfig()[0]
|
||||
print('[wifi] connected:', ip)
|
||||
_show_state('WIFI_OK', ip)
|
||||
utime.sleep(1)
|
||||
utime.sleep(3)
|
||||
return wlan
|
||||
|
||||
|
||||
@@ -167,47 +167,92 @@ def do_checkin(cfg):
|
||||
_show_state('CHECKIN', '')
|
||||
from identity_iot import IdentityIoT
|
||||
|
||||
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']
|
||||
|
||||
identity = IdentityIoT(
|
||||
base_url = cfg['identity_iot_url'],
|
||||
node_type = cfg.get('node_type', 'access_control'),
|
||||
node_label = cfg.get('node_label', ''),
|
||||
tenant_id = cfg['tenant_id'],
|
||||
comm_key = cfg['comm_key'].encode() if isinstance(cfg['comm_key'], str) else cfg['comm_key'],
|
||||
comm_iv = cfg['comm_iv'].encode() if isinstance(cfg['comm_iv'], str) else cfg['comm_iv'],
|
||||
comm_key = key,
|
||||
comm_iv = iv,
|
||||
wifi_ssid = cfg['wifi_ssid'],
|
||||
wifi_pass = cfg['wifi_pass'],
|
||||
)
|
||||
|
||||
# Register (idempotent)
|
||||
_show_state('CHECKIN', 'Registering...')
|
||||
# Register — retry loop
|
||||
for attempt in range(3):
|
||||
try:
|
||||
_show(['CHECKIN', 'Registering...', 'attempt ' + str(attempt+1) + '/3', '', ''])
|
||||
identity.ensure_registered()
|
||||
break
|
||||
except Exception as e:
|
||||
print('[checkin] register attempt', attempt + 1, ':', e)
|
||||
if attempt == 2:
|
||||
_show_state('ERROR', 'Check network')
|
||||
raise
|
||||
utime.sleep(3)
|
||||
|
||||
# Authenticate
|
||||
_show_state('CHECKIN', 'Signing...')
|
||||
# Seconda chiamata idempotente
|
||||
reg = identity.ensure_registered()
|
||||
uid_short = reg.get('node_uid', '')[:12] + '...'
|
||||
_show(['CHECKIN', 'Node ' + reg.get('result', ''), uid_short, '', ''])
|
||||
utime.sleep(1)
|
||||
|
||||
# Authenticate → JWT
|
||||
_show(['CHECKIN', 'Challenge...', '', '', ''])
|
||||
utime.sleep(0.5)
|
||||
_show(['CHECKIN', 'Signing...', '', 'Please wait', ''])
|
||||
token = identity.authenticate()
|
||||
|
||||
if not token:
|
||||
_show_state('ERROR', 'Auth failed')
|
||||
raise Exception('authenticate returned no token')
|
||||
|
||||
print('[checkin] JWT issued')
|
||||
|
||||
# it_node_checkin su identity_tag con JWT
|
||||
_show(['CHECKIN', 'Node checkin...', '', '', ''])
|
||||
import urequests
|
||||
from identity_iot_aes import aes_cbc_encrypt, aes_cbc_decrypt
|
||||
|
||||
payload = ujson.dumps({
|
||||
'request': 'it_node_checkin',
|
||||
'node_id': str(cfg.get('node_id', '')),
|
||||
})
|
||||
cipher = aes_cbc_encrypt(payload, key, iv)
|
||||
body = ujson.dumps({'data': cipher})
|
||||
|
||||
for attempt in range(3):
|
||||
try:
|
||||
token = identity.authenticate()
|
||||
if token:
|
||||
print('[checkin] ok — JWT issued')
|
||||
resp = urequests.post(
|
||||
cfg['identity_tag_url'],
|
||||
headers={
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer ' + token,
|
||||
},
|
||||
data=body,
|
||||
timeout=20,
|
||||
)
|
||||
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('[checkin] node checkin ok')
|
||||
_show_state('CHECKIN OK', cfg.get('node_label', ''))
|
||||
utime.sleep(1)
|
||||
return {'status': 'ok', 'token': token, 'identity': identity}
|
||||
raise Exception('no token')
|
||||
raise Exception('it_node_checkin: ' + str(result.get('code', 'error')))
|
||||
except Exception as e:
|
||||
print('[checkin] auth attempt', attempt + 1, ':', e)
|
||||
print('[checkin] it_node_checkin attempt', attempt + 1, ':', e)
|
||||
if attempt == 2:
|
||||
raise
|
||||
utime.sleep(3)
|
||||
|
||||
raise Exception('checkin failed after 3 attempts')
|
||||
raise Exception('it_node_checkin failed')
|
||||
|
||||
|
||||
# =============================================================================
|
||||
@@ -284,6 +329,8 @@ def run():
|
||||
# ------------------------------------------------------------------
|
||||
elif state == 'CHECKIN':
|
||||
try:
|
||||
import gc
|
||||
gc.collect()
|
||||
checkin_result = do_checkin(cfg)
|
||||
identity = checkin_result.get('identity')
|
||||
state = 'OPERATIONAL'
|
||||
|
||||
@@ -163,9 +163,11 @@ class IdentityIoT:
|
||||
return f.read().strip()
|
||||
except OSError:
|
||||
pass
|
||||
raw_uid = machine.unique_id()
|
||||
h = uhashlib.sha256(raw_uid)
|
||||
uid_hex = ubinascii.hexlify(h.digest()).decode()
|
||||
# Fresh UID — hardware ID + random entropy so each new registration is unique
|
||||
raw_uid = machine.unique_id()
|
||||
entropy = bytes([urandom.getrandbits(8) for _ in range(16)])
|
||||
h = uhashlib.sha256(raw_uid + entropy)
|
||||
uid_hex = ubinascii.hexlify(h.digest()).decode()
|
||||
with open(self._F_NODEID, 'w') as f:
|
||||
f.write(uid_hex)
|
||||
return uid_hex
|
||||
@@ -294,4 +296,4 @@ def _normalize_b64(s: str) -> str:
|
||||
|
||||
|
||||
class StateError(Exception):
|
||||
pass
|
||||
pass
|
||||
Reference in New Issue
Block a user