Hilfe bei der Umsetzung von Java in PHP

Hallo miteinander,
vielleicht kann mir jemand, der Java beherrscht bei einer Codeumsetzung in PHP helfen.
Es geht um folgenden Datensatz von einem Bluetooth LE Sensor:

Data: 0002ad29c9cddf7f370140f080050740700103664bac38

Das hier sollte meiner Meinung nach der Teil des Codes sein, welcher die Sensordaten auswertet:

function t(t,n){
			let r;
			r="xl"!==t.hwFamily?e[2*n+7]:2*e[2*n+7],t.adv[n]={a:e[2*n+6],i:r}
		}
		super(e);
		let n=e[3];
		this.hwFamily=1==(1&n)?"xl":"gen2",
		this.hwVersionNumber=207&n,70!=this.hwVersionNumber&&72!=this.hwVersionNumber||(this.qualityStars=n>>>4&3),
		this.acceloX=this.__getAcceloX(e[2]),
		this.acceloY=this.__getAcceloY(e[2]),
		this.battery=e[4]/256*2+1.5;
		let r=63&e[5];
		if(63==e[5]&&255==e[4]&&(this.corrupted=!0),
		this.temperature=0===r?-40:1.776964*(r-25),
		this.slowUpdateRate=!!(64&e[5]),
		this.syncPressed=!!(128&e[5]),
		this.adv=[],0===n||1===n)t(this,0),t(this,1),t(this,2),t(this,3),t(this,4),t(this,5),t(this,6),t(this,7),
		this.adv.sort((e,t)=>e.i-t.i);
		else{
			let t=0,n=0,r=6;
			for(let a=0;a<12;a+=1){
				let i=10*a,o=Math.floor(i/8),c=i%8,s=e[r+o]+256*e[r+o+1];s>>>=c;
				let A=1+(31&s);s>>>=5;
				let u=31&s,l=n+A;
				if(n=l,l>255)break;
				u&&(u-=1,u*=4,u+=6,this.adv[t]={a:u,i:2*l},t+=1)
			}
		}
	}
	
	__getAcceloY(e){return[-7,1,2,3,4,5,6,0,-6,-5,-8,7,-4,-3,-2,-1][e>>>4&15]}
	__getAcceloX(e){return[-7,1,2,3,4,5,6,0,-6,-5,-8,7,-4,-3,-2,-1][15&e]}

Für die Batterie hab ich mal folgendes getestet:

this.battery=e[4]/256*2+1.5;  // müsste also c9 sein, dezimal 201  ==> 201 ergibt 3,07 (Volt?)

getBatteryPercentage(){let e=this.getBatteryVoltage();return e=(e-2.2)/.65*100,e<0?0:e>100?100:Math.round(e)}    // Alles über 2,85Volt ergibt 100%2,85 -> 100% ; 2,2 -> 0%

Wenn jemand besonders fit in Java ist, würde ich mich über etwas Hilfe freuen.
Ein anderer Sensor der selben Marke wurde hier in Python umgesetzt:
Mopeka pro check

Der Sensor, welcher bei uns erhältlich ist, ist aber keine pro-Version sondern eine andere.

Grüße
Stefan

Das sieht nach einem Quellcode aus der „minified“ wurde. Hast du evtl. das Original im Zugriff?

paresy

Leider habe ich keinen Zugriff auf das Original. Das oben ist nur ein kleiner Auszug vom großen Ganzen.

Hallo Steppe,

bist Du da zu einem Ergebnis gekommen?

Joachim

Hallo Joachim,
ich habe an dem Thema aktuell nicht weiter gearbeitet. Wahrscheinlich werde ich einen Sensor DS1603L mit einem zUno kombinieren um die Füllstandsmessung auf Z-Wave zu bringen - ist mit weniger Aufwand verbunden. Den Sensor hab ich schon an einem Arduino getestet.
Die Anbindung des Mopeka Sensors wäre natürlich schön, da diese günstiger wären als die Kombination von oben.

Grüße
Stefan

Hallo Stefan,

vielen Dank für Deine Rückmeldung.

Ich habe mir mal einen Mopeka-Sensor bestellt, im Zweifelsfall bleibt ja die Anbindung via App.

Beschreibe doch mal bitte was Dir bisher gelungen ist. Hast Du schon selbst Daten empfangen? Wie bist Su dabei vorgegangen?

Joachim

Moin Joachim,
ich würde dir empfehlen den Mopeka Pro Check zu bestellen, da es hier ein Projekt gibt, diesen auszulesen.
Da könnte man dann eher eine Umsetzung für Symcon draus machen.
https://github.com/spbrogan/mopeka_pro_check

Grüße
Stefan

Ich habe eben gesehen, dass es auch eine Wifi-Bridge gibt - ist mir aber mit knapp 100€ zu teuer. Habe jetzt mal einen Pro Sensor bestellt und werde mir das damit mal anschauen.

Hallo Stefan,

bestellt ist ja schon, schauen wir mal wie weit man kommt… :blush:

Hier hat man auch versucht die Daten zu dekodieren.

This is my Palload and some values i am more or less sure what they are:unbenannt.png26 255 13 0 0 2 176 103 234 44 224 129 4 23 28 32 129 4 31 68 112 193 3 96 213 151 248 3 2 160 173

s = static values

MF = manufacturer?

BT? = Battery level?

RT = rate how often the sensor does a messurement /10 in sec means 10.3 sec

Q? = might be the quality of the messurement

MAC = the last three octets of the MAC

Klar ist doch: Der Sensor sendet „Standarddaten“, die Mathematik muss dann im Modul stattfinden, Dein gepostet Ausschnitt kann sicher dabei unterstützen.

Parallel habe ich mal MOPEKA angeschrieben und nach einer Dokumentation des Protokolls gefragt.

Wo hast Du denn Ausschnitt her?
Wie bist Du an den Datensatz oben gekommen?

Joachim

Nachtrag: Schön wäre eigentlich, wenn IP-Symcon selbst ein Bluetooth-I/O (analog z.B. des Seriellen I/O) hätte, so muss man sich um „Basics“ kümmern, würde auf dem Raspberry Pi erst einmal mit den „hcitool“ starten…

Hallo Joachim,
es ist richtig, dass der Sensor nur „Abstandsdaten“ sendet. Die Berechnung über den Füllstand wird dann in der Software gemacht. In der Hersteller-App sind daher auch die verschiedenen Gastankarten hinterlegt um dann die Prozentwerte zu errechnen.

Grüße Stefan

…aktuell sehe ich zwei „große“ Herausforderungen:

  1. Wie bekomme ich es mit einem Raspberry Pi hin, dass die Bluetooth-Daten ins IP-Symcon kommen? Muss ich dazu regelmäßig pollen? Da wäre ich für eine Idee dankbar, möglicherweise hat schon jemand etwas ähnliches umgesetzt…

  2. Wie ist der Datensatz zu interpretieren und mathematisch zu behandeln? Da wird sicherlich einiges „Try and Error“ sein, aber ich hoffe das man das mit den Informationen irgendwie hinbekommt.

Joachim

Hallo Joachim,
ich habe mal wieder ein wenig getestet. Aktuell hole ich mir die Daten folgendermaßen:
Auf dem Raspberry habe ich zum testen folgenden Befehl laufen:

btmon 2>&1 | nc -u 192.168.X.X 8765

Dieser sendet die Daten von btmon an einen UDP-Serversocket mit dem Port 8765 in Symcon.
Bei mir läuft im Hintergrund SymconBTP, daher muss ich folgenden Befehl nicht ausführen:

hcitool -i hci0 lescan > /dev/null 2>&1

An dem UDP-Sockel in IPS hängt dann ein Cutter mit den Einstellungen:
Linkes Trennzeichen: „> HCI“
Rechtes Trennzeichen: „RSSI:“
Ohne Anführungszeichen. Dadurch wird zwar der RSSI-Wert abgeschnitten, ist mir aber erst mal egal.

An dem Cutter hängt dann eine Register-Variable mit folgendem Skript:

$mac = "AA:BB:CC:DD:EE:FF";

if ($_IPS['SENDER'] == "RegisterVariable") {
   $Data = $_IPS['VALUE'];
    if (strpos($Data,$mac)){
        $start = strpos($Data,"Data:");
        echo "Start: ".$start;
        $ende = strpos($Data,chr(10),$start);
        echo "Ende: ".$ende;
        $data = substr($Data,$start,$ende-$start);
        echo $data;
    }
}

Die MAC-Adresse deines Sensors findest du in der APP auf dem Smartphone. Jetzt ist der Daten-String in der Variable $data - fehlt nur noch die Auswertung.
Dazu sind folgende Links interessant:
tankcheck.ts

Mopeka_React-Native

Leider scheint es so zu sein, dass man mit btmon nicht das vollständige Datenpaket bekommt. Daher verwende ich gerade hcitooladv. Damit bekomme ich 31 Bytes an Daten. + RSSI. Das scheint zu passen, da btmon auch Data length: 31 anzeigt.

Aber mit dem Verrechnen der Daten bin ich noch nicht weiter gekommen. Es könnte sogar sein, dass nur die Echo-Zeit des Ultraschalls übergeben wird. Da gibt es im Link oben Berechnungen, wo auch eine Konstante für den Gastyp hinterlegt ist.

Grüße
Stefan

Hallo Stefan,

das sind doch viele wichtige Erkenntnisse!
Habe den Sensor noch nicht, aber mit Deinen Hinweisen, den Informationen aus dem Internet und der App bekommen wir das schon hin!

Joachim

Hallo Stefan,

leider habe ich den Sensor noch nicht erhalten.
Hier gibt es einen Discord-Channel dafür.
Zur Batterie-Spannung steht da z.B. folgendes:

Except for this from Mopeka:
Bits 0-6: Battery voltage scaled such that [0 to 127] represents value [0 to
3.96875 volts]. In other words, read the lower 7 bits into an integer, and
divide by 32 to get the battery voltage

Kannst ja mal schauen ob es bei Dir passt…

Joachim

Den Discord muss ich mir mal anschauen.
Worauf zu achten ist… Es gibt zwei verschiedene Chipsätze, welche auch unterschiedlich ausgewertet werden.
UUID → ADA0 → cc2540
UUID → FEE5 → nrf52

Ich habe den cc2540…

Also mit den Infos vom Github Projekt mopeka_pro_check hab ich den Pro-Sensor auswerten können.

$pro = "AA:BB:CC:DD:EE:FF";

$Data = "AA:BB:CC:DD:EE:FF-0dff590003582f1541ddeeffb0dd0302e5feb3";

   if (strpos($Data,$pro)!==FALSE){
        //echo $Data;
        //01.01.2022, 08:09:10 | Register Variable    | 
        //AA:BB:CC:DD:EE:FF-  
        //0d ff 59 00 03 58  2f   DD EE FF  94  bd  b0    e4    03 02 e5 fe  
        //MA MA HW BAT TEMP Q  Q  MAC MAC MAC XACEL YACEL
        //1  2  3  4   5    6  7  8   9   10  11    12
        //b3 - RSSI
        $start = strpos($Data,"-")+1;
        $data = substr($Data,$start);
        echo "Pro Sensor: ".$data.PHP_EOL;
        //self.ReadingQualityStars = data[7] >> 6
        //""" Confidence or Quality of the reading on a scale of 0-3.  Higher is more confident """
        // self._raw_tank_level = ((int(data[7]) << 8) + data[6]) & 0x3FFF
        $tank = (hexdec($data[16].$data[17])<<8+hexdec($data[14].$data[15]))&0x3FFF;
        echo "Tank: ".$tank.PHP_EOL;
        $quality = hexdec($data[16].$data[17])>>6;
        echo "Quality: ".$quality.PHP_EOL;
        //self._raw_battery = data[4] & 0x7F
        $bat = hexdec($data[10].$data[11])&0x7F;
        echo "Bat raw: ".$bat.PHP_EOL;
        $batvolt = $bat / 32.0;
        echo "Bat volt: ".$batvolt.PHP_EOL;
        //"""Battery Percentage based on 3 volt CR2032 battery"""
        //percent = ((self.BatteryVoltage - 2.2) / 0.65) * 100
        $batper = (($batvolt - 2.2)/0.65)*100;
        echo "Bat percent: ".$batper.PHP_EOL;
        //  self._raw_temp = data[5] & 0x7F
        $temp_raw = hexdec($data[12].$data[13])&0x7F;
        $temp = $temp_raw - 40;
        echo "Temperatur: ".$temp.PHP_EOL;
        /*
        self._raw_tank_level
            * (
                MOPEKA_TANK_LEVEL_COEFFICIENTS_PROPANE[0]
                + (MOPEKA_TANK_LEVEL_COEFFICIENTS_PROPANE[1] * self._raw_temp)
                + (
                    MOPEKA_TANK_LEVEL_COEFFICIENTS_PROPANE[2]
                    * self._raw_temp
                    * self._raw_temp
                )
            )

            # converting sensor value to height - contact Mopeka for other fluids/gases
            MOPEKA_TANK_LEVEL_COEFFICIENTS_PROPANE = (0.573045, -0.002822, -0.00000535)
        */
        $level_mm = $tank * (0.573045+(-0.002822*$temp_raw)+(-0.00000535*$temp_raw*$temp_raw));
        echo "Füllstand: ".$level_mm."mm".PHP_EOL;
   }

Mal sehen, ob sich ohne Informationen vom Hersteller auch der Standard-Sensor auswerten lässt.
Hier sind ja auch Konstanten mit dabei, welche man sich nicht ableiten kann.

Grüße
Stefan

Beim Standard-Sensor hab ich bis jetzt Temperatur, Batterie.
Gerade hänge ich am Füllstand. Dazu müsste ich das hier verstehen und in php umsetzen:

{
      let ndx = 0
      let last_time = 0
      let w = 6

      for (let q = 0; q < 12; q += 1) {
        let bitpos = q * 10
        let bytepos = Math.floor(bitpos / 8)
        let off = bitpos % 8
        let v = mfrData[w + bytepos] + mfrData[w + bytepos + 1] * 256
        /* jslint bitwise: true */
        v = v >>> off
        let dt = (v & 0x1f) + 1
        v = v >>> 5
        let amp = v & 0x1f
        /* jslint bitwise: false */
        let this_time = last_time + dt
        last_time = this_time

        if (this_time > 255) {
          break
        }

        if (!amp) {
          continue
        }
        amp -= 1
        amp *= 4
        amp += 6

        this.adv[ndx] = {
          a: amp,
          i: this_time * 2,
        }
        ndx += 1
      }
    }

Hallo Stefan,

das ist ja klasse wie weit Du schon gekommen bist!!

Leider habe ich bisher den Sensor erhalten (habe das jetzt schon mal per Mail nachgefragt), noch irgendeine Antwort von MOPEKA - Service ist also nicht so deren Business…

Wie auch immer: Irgendwie bekommen wir das schon hin. Ich hatte ja bereits ein passendes Modul begonnen, bisher steht da aber nur ein ganz simples Grundgerüst.

Ich werde mit Deinen Information schon mal das eine oder andere vorbereiten können - ohne es ausprobieren zu können.

Was ist mir bekannt:

  • I/O ist ein UDP-Serversocket
  • die bekannten Statusvariablen Temperatur, Batterie-Spannung, Füllstand
  • gelesen habe ich auch von Empfangsqualität? Oder ist das nur in der Pro-Version?
  • um das Modul einstellen zu können wird sicherlich irgendwie eine Rolle spielen: MAC, Flaschengröße (5kg, 11kg oder sonst etwas)

All diese Dinge kann ich ohne Sensor schon gut vorbereiten, wenn Dir noch etwas einfällt bitte melden!

Joachim

Hallo Stefan,

der Sensor wird nach Aussage leider erst in der nächsten Woche versandt…

Da ich daher noch nicht mal in der App gucken kann, was da so eingestellt werden muss - und ich davon ausgehe das es im Modul nachgebildet werden muss - kannst Du mir ggf. schon mal ein paar Screenshots daraus senden.

Ganz spannend wäre wie die Daten aus dem UDP-I/O ankommen, dann könnte ich da sicherlich schon mal etwas umsetzen bzw. vorbereiten.

Das HCITOOL könnte man schon mal zum Scan benutzen, etwas in der Richtung habe ich bereits vorbereitet, das würde aber ohne Aufwand nur lokal probieren, man könnte es mit der phpseclib aber auch „remote“ machen. Habe ich in anderen Modulen schon so realisiert.

Klasse wäre halt, wenn man es remote nur „anstossen“ würde und dann die Daten per Socket an IP-Symcon gesendet würde…

Joachim