Anwesenheit-Erkennung - Raspi + ESP32 (BLE + Eddystone + BTHome (Shelly) Protokoll)

Einklappen
X
 
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge
  • hismastersvoice
    Supermoderator
    • 25.08.2015
    • 7597

    #46
    AlexAn

    Nochmal eine optimierung...
    PID-Check bevor ich Pharse um keine mehrfache Ausführungen zu bearbeitete.
    sendBatch() das nicht zu viele http reuqests gesendet werden.
    devs + lastPid sind duaerhaft angewachsen, dieser werden jetzt wieder freigegegeben.

    Leider habe ich nur zwei BTHome Geräte... Teste gerne mit mehreren Devices.

    Code:
    let C={
    name:"test",
    host:"192.168.xxx.xxx",
    api_key:"xxxxxxx",
    scan_interval:5,
    hb_interval:10,
    offline_after:30,
    debug:false
    };
    
    let VERSION="1.0.0";
    let BTHOME="fcd2";
    let EDDYSTONE="feaa";
    let CALIB_UUID_PREFIX="B1E0CA11";
    let _P="/shelly/";
    let _H="0123456789abcdef";
    let _s3="\x04\x05\x0A\x42\x4B\x4C";
    let _s4="\x3E\x4D\x4E\x4F\x50";
    let _s2="\x02\x03\x06\x07\x08\x0B\x0C\x0E\x12\x13\x14\x3D\x40\x41\x43\x45\x46\x47\x48\x49\x4A\x51\x52";
    
    function objSize(id){
      let c=String.fromCharCode(id);
      if(_s3.indexOf(c)>=0)return 3;
      if(_s4.indexOf(c)>=0)return 4;
      if(_s2.indexOf(c)>=0)return 2;
      if(id<=0x53)return 1;
      return -1;
    }
    
    let known={};
    let knownUuid={};
    let discMode=false;
    let discDevs={};
    let discTimer=null;
    let devs={};
    let pending=[];
    let ready=false;
    let scanning=false;
    let bootTs=0;
    let lastPid={};
    let calibBuf={};
    let sending=false;
    
    function fastPid(raw){
      if(!raw||raw.length<2)return -1;
      if(raw.charCodeAt(0)&0x01)return -1;
      let i=1;
      while(i<raw.length){
        let id=raw.charCodeAt(i);
        i++;
        if(id===0x00){
          if(i>=raw.length)return -1;
          return raw.charCodeAt(i);
        }
        if(id===0x53){
          if(i>=raw.length)break;
          i+=1+raw.charCodeAt(i);
          continue;
        }
        let size=objSize(id);
        if(size<0)return -1;
        i+=size;
      }
      return -1;
    }
    let batchTimer=null;
    let hbTimer=null;
    let pollTimer=null;
    let retryTimer=null;
    let offlineInitTimer=null;
    
    function ts(){return Math.floor(Date.now()/1000);}
    
    function mem(tag){
      Shelly.call("Sys.GetStatus",{},function(r){
        if(r)print("[MEM] "+tag+" free="+r.ram_free);
      });
    }
    
    function macKey(a){return a.split(":").join("").toLowerCase();}
    
    function toHex(b){return _H[(b>>4)&0xF]+_H[b&0xF];}
    
    function url(p){return "http://"+C.host+":8099"+p;}
    
    function post(p,body,cb){
      if(C.api_key)body.api_key=C.api_key;
      Shelly.call("HTTP.Request",{
        method:"POST",url:url(p),body:JSON.stringify(body),
        content_type:"application/json",timeout:5
      },function(r,ec){
        if(ec!==0||!r||!r.body){if(cb)cb(null);return;}
        try{if(cb)cb(JSON.parse(r.body));}catch(e){if(cb)cb(null);}
      });
    }
    
    function get(p,cb){
      let u=url(p);
      if(C.api_key)u+=(u.indexOf("?")>=0?"&":"?")+"api_key="+C.api_key;
      Shelly.call("HTTP.Request",{
        method:"GET",url:u,timeout:5
      },function(r,ec){
        if(ec!==0||!r||!r.body){if(cb)cb(null);return;}
        try{if(cb)cb(JSON.parse(r.body));}catch(e){if(cb)cb(null);}
      });
    }
    
    function parseBTHome(raw){
      if(!raw||raw.length<2)return null;
      let result={pid:-1,battery:-1,button:-1};
      if(raw.charCodeAt(0)&0x01)return null;
      let i=1;
      while(i<raw.length){
        let id=raw.charCodeAt(i);
        i++;
        if(id===0x53){
          if(i>=raw.length)break;
          i+=1+raw.charCodeAt(i);
          continue;
        }
        let size=objSize(id);
        if(size<0||i+size>raw.length)break;
        if(id===0x00||id===0x01||id===0x3A){
          let val=0;
          for(let b=0;b<size;b++){
            val=val+(raw.charCodeAt(i+b)<<(b*8));
          }
          if(id===0x00)result.pid=val;
          else if(id===0x01)result.battery=val;
          else if(id===0x3A)result.button=val;
        }
        i+=size;
      }
      return result;
    }
    
    function parseEddystoneBatt(raw){
      if(!raw||raw.length<4)return -1;
      if(raw.charCodeAt(0)!==0x20)return -1;
      let mV=(raw.charCodeAt(2)<<8)|raw.charCodeAt(3);
      if(mV===0)return -1;
      let pct=Math.round((mV-2000)/10);
      if(pct<0)return 0;
      if(pct>100)return 100;
      return pct;
    }
    
    function parseIBeacon(advData){
      if(!advData)return null;
      let raw=BLE.GAP.ParseManufacturerData(advData);
      if(!raw||raw.length<25)return null;
      if(raw.charCodeAt(0)!==0x4C||raw.charCodeAt(1)!==0x00)return null;
      if(raw.charCodeAt(2)!==0x02||raw.charCodeAt(3)!==0x15)return null;
      let u="";
      for(let i=4;i<20;i++){
        u+=toHex(raw.charCodeAt(i));
        if(i===7||i===9||i===11||i===13)u+="-";
      }
      let txp=raw.charCodeAt(24);
      if(txp>127)txp-=256;
      return {uuid:u,major:(raw.charCodeAt(20)<<8)|raw.charCodeAt(21),minor:(raw.charCodeAt(22)<<8)|raw.charCodeAt(23),txpower:txp};
    }
    
    function isCalibBeacon(ib){
      if(!ib||!ib.uuid)return false;
      return ib.uuid.substring(0,8).toUpperCase()===CALIB_UUID_PREFIX;
    }
    
    function handleCalibBeacon(ib,rssi){
      let key=ib.major+":"+ib.minor;
      let e=calibBuf[key];
      if(!e){e={s:0,c:0,t:ib.txpower};calibBuf[key]=e;}
      e.s+=rssi;
      e.c++;
    }
    
    function sendCalibration(){
      let readings=[];
      for(let key in calibBuf){
        let e=calibBuf[key];
        if(e.c===0)continue;
        let parts=key.split(":");
        let avg=Math.round(e.s/e.c);
        readings.push({major:parseInt(parts[0]),minor:parseInt(parts[1]),rssi:avg,distance:Math.round(Math.pow(10,(e.t-avg)/25)*100)/100});
      }
      calibBuf={};
      if(readings.length===0)return;
      if(C.debug)print("[CAL] "+readings.length);
      post(_P+"calibration",{scanner:C.name,readings:readings},null);
    }
    
    function sendButtonEvent(mac,event,rssi,pid){
      let names=["none","press","double_press","triple_press","long_press"];
      let name=(event>=1&&event<=4)?names[event]:"unknown";
      if(C.debug)print("[BTN] "+mac+" -> "+name+" pid="+JSON.stringify(pid));
      post(_P+"event",{scanner:C.name,mac:mac,event:name,rssi:rssi,pid:pid,timestamp:ts()},null);
    }
    
    function loadKnown(macs){
      known={};
      knownUuid={};
      if(!macs)return;
      for(let i=0;i<macs.length;i++){
        let m=macs[i];
        if(m.length===12)known[m]=true;
        else if(m.length===36&&m.indexOf("-")>0)knownUuid[m]=true;
      }
    }
    
    function register(){
      print("[REG] Registering...");
      let info=Shelly.getDeviceInfo();
      let wifi=Shelly.getComponentStatus("wifi");
      post(_P+"register",{
        scanner:C.name,
        ip:(wifi&&wifi.sta_ip)?wifi.sta_ip:"0.0.0.0",
        model:info?(info.model||"Shelly"):"Shelly",
        firmware:info?(info.fw_id||"?"):"?",
        scan_interval:C.scan_interval
      },function(d){
        if(!d||!d.success){
          print("[REG] Failed, retry 10s");
          if(retryTimer)Timer.clear(retryTimer);
          retryTimer=Timer.set(10000,false,register);
          return;
        }
        loadKnown(d.known_macs);
        if(C.debug){
          let cM=0,cU=0;
          for(let k in known)cM++;
          for(let k in knownUuid)cU++;
          print("[REG] OK: "+cM+"M "+cU+"U");
        }else{
          print("[REG] OK");
        }
        mem("post-reg");
        if(d.scan_interval)C.scan_interval=d.scan_interval;
        ready=true;
        startScan();
        startTimers();
      });
    }
    
    function startScan(){
      if(scanning)return;
      BLE.Scanner.Subscribe(onScan);
      BLE.Scanner.Start({duration_ms:-1,active:true});
      scanning=true;
    }
    
    function onScan(ev,res){
      if(ev!==BLE.Scanner.SCAN_RESULT||!res||!res.addr)return;
    
      if(discMode){
        let mac=res.addr.toUpperCase();
        let ib=parseIBeacon(res.advData);
        let dk=ib?ib.uuid:macKey(mac);
        if(!discDevs[dk]||res.rssi>discDevs[dk].r){
          let entry={m:mac,n:res.local_name||"",r:res.rssi,tp:"mac"};
          if(ib){
            entry.tp="ibeacon";
            entry.iu=ib.uuid.toUpperCase();
            entry.ima=ib.major;
            entry.imi=ib.minor;
          }else if(res.service_data&&res.service_data[BTHOME]){
            entry.tp="bthome";
          }
          discDevs[dk]=entry;
        }
        return;
      }
    
      let ib=parseIBeacon(res.advData);
      if(ib&&isCalibBeacon(ib)){
        handleCalibBeacon(ib,res.rssi);
        return;
      }
    
      let mac=res.addr.toUpperCase();
      let mk=macKey(mac);
      let isMac=known[mk]===true;
      let isUuid=false;
      let dk=mk;
    
      if(!isMac){
        if(ib&&knownUuid[ib.uuid]){
          isUuid=true;
          dk=ib.uuid;
        }else{
          return;
        }
      }
    
      let t=ts();
      let d=devs[dk];
      if(!d){
        d={o:false,s:0,r:-100,m:mac,t:0,b:-1,u:isUuid,ui:""};
        devs[dk]=d;
      }
    
      d.s=t;
      d.r=res.rssi;
      d.m=mac;
      if(isUuid&&ib)d.ui=ib.uuid;
    
      let raw=res.service_data?res.service_data[BTHOME]:null;
    
      if(raw){
        let pid=fastPid(raw);
        if(pid>=0){
          if(lastPid[dk]===pid)return;
          lastPid[dk]=pid;
        }
      }
    
      let bth=null;
      if(raw)bth=parseBTHome(raw);
    
      if(bth&&bth.battery>=0&&bth.battery<=100)d.b=bth.battery;
    
      if(d.b<0&&res.service_data&&res.service_data[EDDYSTONE]){
        let eB=parseEddystoneBatt(res.service_data[EDDYSTONE]);
        if(eB>=0)d.b=eB;
      }
    
      if(bth&&bth.button>=1){
        sendButtonEvent(mac,bth.button,res.rssi,bth.pid);
      }
    
      let wasOff=!d.o;
      d.o=true;
    
      let scan={address:mac,rssi:res.rssi,is_online:1,local_name:""};
      if(d.b>=0)scan.battery=d.b;
    
      if(isUuid&&ib){
        scan.ibeacon_uuid=ib.uuid;
        scan.ibeacon_major=ib.major;
        scan.ibeacon_minor=ib.minor;
        scan.ibeacon_txpower=ib.txpower;
      }
    
      if(wasOff){
        if(C.debug){
          let l=isUuid?dk.substring(0,8)+"...":mac;
          print("[ON] "+l+" R:"+res.rssi);
        }
        if(pending.length<20)pending.push(scan);
        d.t=t;
        sendBatch();
      }else if(t-d.t>=C.scan_interval){
        if(pending.length<20)pending.push(scan);
        d.t=t;
      }
    }
    
    function checkOffline(){
      let t=ts();
      let ct=C.offline_after*3;
      for(let mk in devs){
        let d=devs[mk];
        let age=t-d.s;
        if(d.o&&age>=C.offline_after){
          d.o=false;
          d.t=t;
          if(C.debug){
            let l=d.u?d.ui.substring(0,8)+"...":d.m;
            print("[OFF] "+l);
          }
          let os={address:d.m,rssi:-100,is_online:0,local_name:""};
          if(d.u&&d.ui)os.ibeacon_uuid=d.ui;
          if(pending.length<20)pending.push(os);
        }
        if(!d.o&&age>=ct){
          delete devs[mk];
          delete lastPid[mk];
        }
      }
    }
    
    function sendBatch(){
      if(!ready||sending)return;
      checkOffline();
      if(pending.length===0)return;
      let scans=pending;
      pending=[];
      sending=true;
      if(C.debug)print("[TX] "+scans.length);
      post(_P+"scan",{scanner:C.name,scans:scans,discovery:false},function(d){
        sending=false;
        if(!d)print("[ERR] Batch failed");
      });
    }
    
    function heartbeat(){
      if(!ready)return;
      sendCalibration();
      Shelly.call("Sys.GetStatus",{},function(sr){
        let hb={scanner:C.name,uptime:ts()-bootTs};
        if(sr&&sr.ram_free){
          hb.free_mem=sr.ram_free;
          if(C.debug)print("[MEM] hb free="+sr.ram_free);
        }
        post(_P+"heartbeat",hb,function(d){
          if(!d||!d.success){
            print("[ERR] HB failed");
            ready=false;
            if(retryTimer)Timer.clear(retryTimer);
            retryTimer=Timer.set(5000,false,register);
          }
        });
      });
    }
    
    function offlineInit(){
      offlineInitTimer=null;
      let cnt=0;
      for(let mk in known){
        if(!devs[mk]){
          if(pending.length<20){
            pending.push({address:mk,rssi:-100,is_online:0,local_name:""});
            cnt++;
          }
        }
      }
      for(let uu in knownUuid){
        if(!devs[uu]){
          let c="";
          for(let j=0;j<uu.length;j++){
            if(uu.charAt(j)!=="-")c+=uu.charAt(j);
          }
          if(pending.length<20){
            pending.push({address:c,rssi:-100,is_online:0,local_name:"",ibeacon_uuid:uu});
            cnt++;
          }
        }
      }
      if(cnt>0)sendBatch();
    }
    
    function startTimers(){
      if(batchTimer)Timer.clear(batchTimer);
      batchTimer=Timer.set(C.scan_interval*1000,true,sendBatch);
      if(hbTimer)Timer.clear(hbTimer);
      hbTimer=Timer.set(C.hb_interval*1000,true,heartbeat);
      if(offlineInitTimer)Timer.clear(offlineInitTimer);
      offlineInitTimer=Timer.set(C.offline_after*1000,false,offlineInit);
      if(pollTimer)Timer.clear(pollTimer);
      pollTimer=Timer.set(300000,true,pollDevices);
    }
    
    function startDiscovery(duration){
      if(discMode)return "already running";
      if(!duration||duration<5)duration=15;
      discMode=true;
      discDevs={};
      if(discTimer)Timer.clear(discTimer);
      discTimer=Timer.set(duration*1000,false,discEnd);
      return "started";
    }
    
    function discEnd(){
      discMode=false;
      discTimer=null;
      sendDiscoveryResults();
    }
    
    function sendDiscoveryResults(){
      let devices=[];
      for(let k in discDevs){
        let dd=discDevs[k];
        let entry={mac:dd.m,name:dd.n,rssi:dd.r,type:dd.tp};
        if(dd.iu){
          entry.ibeacon_uuid=dd.iu;
          entry.ibeacon_major=dd.ima;
          entry.ibeacon_minor=dd.imi;
        }
        devices.push(entry);
      }
      discDevs={};
      let dUrl="http://"+C.host+"/ble/api.php?action=report_discovery";
      if(C.api_key)dUrl+="&api_key="+C.api_key;
      Shelly.call("HTTP.Request",{
        method:"POST",url:dUrl,
        body:JSON.stringify({client_id:C.name,timestamp:ts(),devices:devices}),
        content_type:"application/json",timeout:15
      },function(r,ec){
        if(ec!==0||!r||r.code!==200)print("[DISC] Send failed");
      });
    }
    
    function pollDevices(){
      get(_P+"devices?scanner="+C.name,function(d){
        if(!d||!d.success||!d.known_macs)return;
        loadKnown(d.known_macs);
      });
    }
    
    function status(){
      let kon=0,koff=0,kn=0,ku=0;
      for(let mk in devs){if(devs[mk].o)kon++;else koff++;}
      for(let k in known)kn++;
      for(let k in knownUuid)ku++;
      return JSON.stringify({ready:ready,known_mac:kn,known_uuid:ku,online:kon,offline:koff,uptime:ts()-bootTs,pending:pending.length,discovery:discMode});
    }
    
    bootTs=ts();
    print("=== BLE Presence Shelly v"+VERSION+" ===");
    print("[BLE] "+C.name+" -> "+C.host+(C.api_key?" [API]":" [NO KEY]"));
    mem("boot");
    retryTimer=Timer.set(3000,false,register);







    Kein Support per PN!

    Kommentar

    • AlexAn
      Lebende Foren Legende
      • 25.08.2015
      • 4555

      #47
      Hab 8 und 9 BTHome Gräte jeweils bei den 2 Scanner laufen.
      Script läuft und ich füge die H&T wieder hinzu.

      Kann sich das iPhone nur am Master einloggen bzw. ist die Funktion noch in Arbeit?

      Die Kalibrierung muss ich vermutlich auch noch anpassen.
      Klicke auf die Grafik für eine vergrößerte Ansicht

Name: image.png
Ansichten: 97
Größe: 463,1 KB
ID: 480724
      Zuletzt geändert von AlexAn; In den letzten 4 Wochen.
      Grüße Alex

      Kommentar


      • hismastersvoice
        hismastersvoice kommentierte
        Kommentar bearbeiten
        Das iPhone geht nur mit IRK und das geht nur mit ESP32 Scannern und am Master.
        Die Shelly haben die nötigen Crypto-Libs nicht in der Firmware (Braucht auch viel Speicher).

        iPhone geht auch nur wenn min 2 iPhones in der der Cloud angemeldet sind oder iPhone mit Apple Watch.
        Ansonsten sind sie nach einer Minute still.
        Das ist aber ein Problem das alle haben, nicht nur mein Projekt.

      • AlexAn
        AlexAn kommentierte
        Kommentar bearbeiten
        Watch und iPad hab ich in der gleichen iCloud.
        XIAO ESP32-S3 sind bestellt...
        Die ESP32-WROM D1 Mini zicken beim flashen rum das gibt´s gar nicht.
        Zuletzt geändert von AlexAn; In den letzten 4 Wochen.

      • hismastersvoice
        hismastersvoice kommentierte
        Kommentar bearbeiten
        Habe gerade einen D1 Mini über das Web Flash Tool installiert, ohne Fehler.
        Was für ein Problem machen die Dinger bei dir?
    • AlexAn
      Lebende Foren Legende
      • 25.08.2015
      • 4555

      #48
      Klicke auf die Grafik für eine vergrößerte Ansicht

Name: image.png
Ansichten: 107
Größe: 34,4 KB
ID: 480736 Klicke auf die Grafik für eine vergrößerte Ansicht

Name: image.png
Ansichten: 106
Größe: 630,7 KB
ID: 480737

      danach möchte er wieder von vorne das File installieren
      Klicke auf die Grafik für eine vergrößerte Ansicht

Name: image.png
Ansichten: 102
Größe: 48,0 KB
ID: 480738

      Sind von AZ Delivery
      Tasmota bekomm ich rauf.

      Grüße Alex

      Kommentar

    • hismastersvoice
      Supermoderator
      • 25.08.2015
      • 7597

      #49
      AlexAn

      Fehler ist klar...
      Tasmota hat einen andere Partionstabelle als ich...

      Habe in flash.php die Option "Erase Flash" eingebaut. Dann macht er das Gerät erst mal leer und dann sollte das Flashen gehen.
      Klicke auf die Grafik für eine vergrößerte Ansicht  Name: grafik.png Ansichten: 0 Größe: 102,7 KB ID: 480743

      PS ggf. das Gerät von USB trennen und wieder einstecken vor dem flashen.
      Zuletzt geändert von hismastersvoice; In den letzten 4 Wochen.
      Kein Support per PN!

      Kommentar

      • AlexAn
        Lebende Foren Legende
        • 25.08.2015
        • 4555

        #50
        Danke für dein Mühe!!
        Denke meine D1 Mini sind einfach hinüber und ich warte auf die Lieferung.
        Löschen hat funktioniert aber dann kommt wieder die Fehlermeldung:
        Klicke auf die Grafik für eine vergrößerte Ansicht

Name: image.png
Ansichten: 109
Größe: 400,5 KB
ID: 480750
        Grüße Alex

        Kommentar


        • hismastersvoice
          hismastersvoice kommentierte
          Kommentar bearbeiten
          Manifest heißt er will eigentlich eine eigene Firmware Version. Aber FF ist kein Magic Byte, FF heißt einfach nur leer.
      • AlexAn
        Lebende Foren Legende
        • 25.08.2015
        • 4555

        #51
        Kann es sein dass das Update für den Master/Raspberry noch nicht freigegeben ist?
        Reboot hab ich gemacht.
        Klicke auf die Grafik für eine vergrößerte Ansicht

Name: image.png
Ansichten: 104
Größe: 83,0 KB
ID: 480782
        Grüße Alex

        Kommentar

        • hismastersvoice
          Supermoderator
          • 25.08.2015
          • 7597

          #52
          Mein deployment Script hat die version.json nicht überschrieben. Du hast die 1.0.1 installiert das File ist aber bei 1.0.0 stehen geblieben.
          Ich habe die Version 1.0.2 hochgeladen versuch es mal.

          Wenn es zu einem Fehler kommt.
          Code:
          version": "%s"\n}\n' "1.0.2" > /var/www/html/ble/version.json
          Dann nochmal die 1.0.2 installieren.
          Kein Support per PN!

          Kommentar


          • AlexAn
            AlexAn kommentierte
            Kommentar bearbeiten
            super Danke hat geklappt
            nach dem 2.mal hat er es geschluckt genau wie du geschrieben hast
        • Prof.Mobilux
          Supermoderator
          • 25.08.2015
          • 5295

          #53
          Als ob Du es gewusst hättest

          Version 17:

          Code:
          - A3D9-T2094: New Function Block - Presence Central
          - Get a combined overview of the presence in a building
          - Longterm Absence pulse
          - Auto Config will enable house in deep sleep on longterm absence
          - App support will be added in the next weeks
          🇺🇦 Hilfe für die Menschen der Ukraine: https://www.loxforum.com/forum/proje...Cr-die-ukraine


          LoxBerry - Beyond the Limits

          Kommentar


          • hismastersvoice
            hismastersvoice kommentierte
            Kommentar bearbeiten
            Das ist schon eine ganze Weile drin, damit sind aber die eigenen Präsenzbausteine gemeint, die summiert dargestellt werden.
            Aber man kann es dafür natürlich perfekt nutzen.
        • AlexAn
          Lebende Foren Legende
          • 25.08.2015
          • 4555

          #54
          D1Mini: läuft (nodemcu-pyflasher)
          iPhone: läuft
          17er: läuft
          Feintuning der Position: offen (leider nicht alle Scanner in Lichtschalterhöhe)

          Umbau kann beginnen
          Grüße Alex

          Kommentar


          • hismastersvoice
            hismastersvoice kommentierte
            Kommentar bearbeiten
            -Feintuning der Position: offen (leider nicht alle Scanner in Lichtschalterhöhe)

            Das macht nichts...
            Dafür habe ich die Funktion Auto-Calibartion eingebaut.
            Wenn mehr als zwei Scanner (ESP32) vorhanden sind, und es an ESPs und Master aktiv ist, sendet jeder ESP32 ein iBeacon-Signal, alle anderen Empfangen und sammeln die Daten und geben sie gesammelt weiter (RSSI). Der Aggregator berechnet automatisch die Scanner-Offsets, und nutzt sie für eine verbesserte Positioning.
            Somit ist es nicht mehr ganz so wichtig wo genau jeder Scanner sitzt, natürlich je gleichmäßig verteile desto besser.
        • f.hien
          LoxBus Spammer
          • 31.08.2015
          • 392

          #55
          Hallo zusammen, ich bin gerade auf eure Entwicklung aufmerksam geworden, habe eine Fragen dazu, Diet Pi ist standart könnte also auch auf Hyperv laufen?
          2. ESP Scanner habt ihr auch welche mit 24V die wäre anliegend. ( wenn nicht dann muss ich mit DC-DC reglern abreiten). habt ihr erfahrung mit Einbau in Dosen?
          3. Funktionieren die Alten G-tag, diese habe ich im Moment im einsatz. für meine Auto's läuft seid 2016 mehr oder weniger stabil. das würde ich vielleicht ablösen.

          Danke für die Super arbeit.

          Kommentar


          • hismastersvoice
            hismastersvoice kommentierte
            Kommentar bearbeiten
            Besser spät als nie...
            1. Ja sollte auf allen DietPi Versionen laufen, du hast dann halt kein BLE am Master
            2. Die musst man selber bauen, ich habe mir kleine Platinen mit einem Mini-Stepdown gelötet.
            3. Ja, mit den G-Tags habe ich das Projekt gestartet, erst später ist Eddystone und BTHome dazu gekommen. '
        Lädt...