Android Code Snippet Shelly PlugS Gen3 B4A Bluetooth

Hi everyone,
Here's a class for turning the Shelly PlugS Gen3 on and off in B4A via Bluetooth.


Sub Process_Globals:
Dim ShellyBT As ShellyBluetoothController

Sub Activity_Create(FirstTime As Boolean):
    If FirstTime Then
        ShellyBT.Initialize
        Sleep(500)   
        ShellyBT.StartController
    End If

The class is called as follows:

Sub PhoneEvents_BatteryChanged:
Sub PhoneEvents_BatteryChanged (Level As Int, Scale As Int, Plugged As Boolean, Intent As Intent)
' Diese Methode wird aufgerufen, wenn sich der Batteriestatus ändert
    batteryPercentage = (Level / Scale) * 100
    'Log($"Batteriestatus: ${batteryPercentage}%"$)
        
        'Prüfe erst ab einem bestimmten Bereich
                If batteryPercentage <= 20 Or batteryPercentage >= 80 Then
                    ShellyBT.SetBattery(batteryPercentage)
                End If
End Sub

Here is the class:

ShellyBluetoothController:
'Klasse: ShellyBluetoothController
'Zweck: Automatisches Laden via Shelly BLE (Scan -> Connect -> Switch -> Disconnect)
Sub Class_Globals
    Private ShellyBLE As BleManager2
    Private ConnectedDevice As String = ""
    Private CanWrite As Boolean = False
    
    ' Deine spezifischen Shelly UUIDs
    Private ServiceUUID As String = "5f6d4f53-5f52-5043-5f53-56435f49445f"
    Private CharUUID As String = "5f6d4f53-5f52-5043-5f64-6174615f5f5f"
    
    ' Status-Variablen
    Private Charging As Boolean = False
    Private LastBattery As Int = -1
    Private TimerCheck As Timer
    Private LastSwitchTime As Long = 0
    Private MinSwitchInterval As Long = 60000
    Private IsWorking As Boolean = False
    
    ' Schwellwerte für die Automatik
    Private LadenAnschalten As Int = 20
    Private LadenAbschalten As Int = 80
    Private NotLadenAnschalten As Int = 18
    Private NotLadenAbschalten As Int = 82
End Sub

' Initialisierung
Public Sub Initialize
    ShellyBLE.Initialize("ShellyBLE")
    TimerCheck.Initialize("TimerCheck", 60000) ' Alle 60 Sekunden prüfen
End Sub

' Controller starten
Public Sub StartController
    Log("Shelly BLE Controller aktiv.")
    TimerCheck.Enabled = True
End Sub

' Controller stoppen
Public Sub StopController
    TimerCheck.Enabled = False
    ResetBLE
End Sub

' Batterie-Wert von außen füttern
Public Sub SetBattery(batteryPercentage As Int)
    LastBattery = batteryPercentage
End Sub

' --- Kern-Logik: Timer Event ---
Private Sub TimerCheck_Tick
    ' Falls wir gerade schon arbeiten oder kein Batteriewert da ist: Abbruch
    If IsWorking Or LastBattery < 0 Then Return
    
    ' Prüfen: Besteht Handlungsbedarf?
    Dim AktionNötig As Boolean = False
    
    If LastBattery <= LadenAnschalten And Charging = False Then AktionNötig = True
    If LastBattery >= LadenAbschalten And Charging = True Then AktionNötig = True
    If LastBattery <= NotLadenAnschalten Then AktionNötig = True
    If LastBattery >= NotLadenAbschalten Then AktionNötig = True
    
    If AktionNötig Then
        ' Schaltintervall Schutz prüfen
        If DateTime.Now - LastSwitchTime < MinSwitchInterval Then
            Log("Aktion nötig, aber Sicherheits-Intervall läuft noch.")
            Return
        End If
        
        IsWorking = True
        SucheUndSchalte
    Else
        Log("Batterie ok (" & LastBattery & "%). Keine BLE-Aktion nötig.")
    End If
End Sub

' --- Der Ablauf-Prozess (Resumable Sub) ---
Private Sub SucheUndSchalte
    Log("Starte BLE-Ablauf...")
    
    ' Falls noch Reste einer alten Verbindung da sind
    ResetBLE
    IsWorking = True ' ResetBLE setzt es auf False, wir brauchen es hier True
    
    ' 1. Scan starten
    ShellyBLE.Scan2(Null, False)
    
    ' 2. Timeout abwarten (10 Sekunden suchen)
    Sleep(10000)
    
    ' 3. Ergebnis prüfen
    If ConnectedDevice = "" Then
        Log("Timeout: Shelly nicht gefunden.")
        ShellyBLE.StopScan
        IsWorking = False
    Else
        ' Wir sind verbunden. ble_Connected hat bereits SwitchShelly getriggert.
        ' Wir warten noch kurz, bis der Disconnect durch ist.
        Sleep(2000)
        IsWorking = False
        Log("Ablauf beendet, Bluetooth wieder im Tiefschlaf.")
    End If
End Sub

' --- BLE Events ---

Private Sub ShellyBLE_DeviceFound (Name As String, Id As String, AdvertisingData As Map, RSSI As Double)
    If Name = Null Then Return
    If Name.ToLowerCase.Contains("shelly") Then
        Log("Shelly gefunden: " & Name)
        ShellyBLE.StopScan
        ConnectedDevice = Id
        ShellyBLE.Connect(Id)
    End If
End Sub

Private Sub ShellyBLE_Connected (Services As List)
    Log("✓ Verbunden. Initialisiere...")
    ShellyBLE.RequestMtu(128)
    Sleep(500)
    
    Try
        ' Benachrichtigungen aktivieren
        ShellyBLE.SetNotify(ServiceUUID, CharUUID, True)
        CanWrite = True
        
        ' Sofort Schalten
        ProcessBatteryLogic
    Catch
        Log("Fehler beim Setup der Services: " & LastException)
        ResetBLE
    End Try
End Sub

Private Sub ShellyBLE_Disconnected
    Log("Verbindung getrennt.")
    ConnectedDevice = ""
    CanWrite = False
End Sub

' --- Schaltvorgang ---

Private Sub ProcessBatteryLogic
    ' Hier entscheiden wir final über den Status
    Dim TargetState As Boolean = Charging
    
    If LastBattery <= LadenAnschalten Then TargetState = True
    If LastBattery >= LadenAbschalten Then TargetState = False
    
    ' Notfall-Werte
    If LastBattery <= NotLadenAnschalten Then TargetState = True
    If LastBattery >= NotLadenAbschalten Then TargetState = False
    
    SwitchShelly(TargetState)
End Sub

Private Sub SwitchShelly(State As Boolean)
    If Not(CanWrite) Then Return
    
    Dim json As String = $"{"id":1,"src":"app","method":"Switch.Set","params":{"id":0,"on":${State}}}"$
    Dim bytes() As Byte = json.GetBytes("UTF8")
    
    Try
        Log("Sende RPC: " & json)
        ShellyBLE.WriteData(ServiceUUID, CharUUID, bytes)
        Charging = State
        LastSwitchTime = DateTime.Now
        
        ' Warten auf Verarbeitung, dann kappen
        Sleep(1500)
        Log("Schaltbefehl fertig. Trenne...")
        ResetBLE
    Catch
        Log("Schreibfehler: " & LastException)
        ResetBLE
    End Try
End Sub

' Datenempfang (optional, falls du die Antwort loggen willst)
Private Sub ShellyBLE_DataAvailable (Service As String, Characteristics As Map)
    If Characteristics.ContainsKey(CharUUID) Then
        Dim Value() As Byte = Characteristics.Get(CharUUID)
        Log("Shelly Antwort: " & BytesToString(Value, 0, Value.Length, "UTF8"))
    End If
End Sub

' Hilfs-Sub für sauberen Status
Private Sub ResetBLE
    If ConnectedDevice <> "" Then
        Try
            ShellyBLE.Disconnect
        Catch
            Log("ResetBLE")
        End Try
    End If
    ShellyBLE.StopScan
    ConnectedDevice = ""
    CanWrite = False
    IsWorking = False
End Sub

' UI Info Helper
Public Sub GetStatusText As String
    Return "Batterie: " & LastBattery & "% | Laden: " & Charging & " | Aktiv: " & IsWorking
End Sub
 

Wolli013

Well-Known Member
Licensed User
Longtime User
Does anyone know how to turn off the blue flashing light on the access point via BLE so that no lights are on at all, regardless of which one?
 
Top