Sensus iPerl ESPHome Setup — Meter ID, AES Key & Full YAML Config [Part 2]

Mark
Autor
Sensus iPerl ESPHome Setup — Meter ID, AES Key & Full YAML Config [Part 2]

Did you like this article?

Creating guides takes a lot of time, and I don’t want ads on the site. If I’ve helped you and you feel like it — buy me a coffee. It really motivates me to keep writing!

In Part 1 you wired the hardware. Now we configure the software. This part covers the two things most guides skip: where to find your Meter ID on the iPerl label, and the default AES-128 key that works for most installations. Then we walk through the complete ESPHome YAML and flash it to the NodeMCU.
Before you start:
— Hardware from Part 1 assembled (NodeMCU V3 + E07-900M10S wired up)
— Home Assistant running with the ESPHome add-on installed
— Physical access to the meter, or willingness to flash with log_unknown: True first

Step 1 — Find your Meter ID

The Meter ID uniquely identifies your water meter. The wmbus component uses it to filter your meter’s telegrams from all the others transmitting nearby — in an apartment building there can be a dozen meters on the same frequency simultaneously. Two ways to find it:
Method 1 — label on the meter (faster)
On the Sensus iPerl housing, in the top right corner, there is a serial number starting with 8 SEN. The digits after those characters are your Meter ID.
Example label:
8 SEN 2086 3703
Label: 8 SEN 2086 3703
YAML: meter_id: “0x20863703”
Method 2 — log_unknown in ESPHome (when label is unreadable)
Flash the firmware with meter_id: "0x00000000" and log_unknown: true. ESPHome will log every wMBus telegram it receives, including the Meter ID for each one.
What you will see in the ESPHome Dashboard log:
[D][wmbus:176]: Meter ID [0x20863703] RSSI: -56 dBm LQI: 128
                          ^^^^^^^^^^^
                          This is your Meter ID
The ID that appears regularly is your meter. Neighbours’ meters will also appear but each has a different ID. Note: logs are only visible in the ESPHome Dashboard Logs tab — not in the web panel at water-meter-nmc.local.

Step 2 — AES-128 encryption key

wMBus telegrams are AES-128 encrypted. Without the correct key ESPHome receives the signal but cannot read any values — it sees only an encrypted byte stream.
Default factory key — Sensus iPerl
Most utility companies do not change this key. If your meter has its original factory configuration, this works immediately:
Default AES-128 key — Sensus iPerl:
E6C88800DEB868C0D6A84880CE982840
If the key does not work:
No 2F2F check after decrypting - OK in the log means the key was changed by your utility. Request it from your building manager or water company — as the meter owner you are entitled to it.

Step 3 — New device in ESPHome Dashboard

1

In ESPHome Dashboard click + New Device
2

Enter device name e.g. water-meter-nmc — lowercase, no spaces
3

Select platform ESP8266
4

Click Edit on the new device and replace the entire content with the YAML below

Step 4 — ESPHome YAML configuration

 Never put passwords in YAML — use secrets.yaml
Store credentials in /config/esphome/secrets.yaml:

wifi_ssid: "YourNetworkName"
wifi_password: "YourWiFiPassword"
ota_password: "AnyOTAPassword"

The YAML below reads from secrets.yaml automatically using !secret syntax.

Two-step process for finding Meter ID:
Step 1: Flash with meter_id: "0x00000000" and log_unknown: true. Open ESPHome Dashboard Logs and wait for a telegram.
Step 2: Fill in your Meter ID, set log_unknown: false, reflash via OTA.Important: The iPerl transmission interval is set by your water utility — typically 10–30 minutes during the day and much less frequent at night. Do not assume something is broken if the log is silent for 15–30 minutes. Just wait.

## ------------------------------------------------------------------
## WMBUS NodeMCU V3 + EBYTE E07-900M10S (CC1101 868MHz)
## Supports 30 wMBus meter types (water, gas, heat, electricity)
## External component: github.com/SzczepanLeon/esphome-components
## Credits: based on ha-watermeter by Peter Siebler (zibous)
## ------------------------------------------------------------------
substitutions:
  device_name_short: "water-meter-nmc"
  friendly_name: "Watermeter"
  appversion: "3.0.0"
  log_level: "WARN"      # Production: WARN | Debugging: VERY_VERBOSE
  log_wmbus: "WARN"      # Production: WARN | Debugging: VERY_VERBOSE
  log_baudrate: "0"      # 0 = disable UART logging

esp8266:
  board: nodemcuv2
  restore_from_flash: true

esphome:
  name: ${device_name_short}
  on_boot:
    then:
      - globals.set:
          id: boot_counter
          value: !lambda "return id(boot_counter)+=1;"
      - globals.set:
          id: send_millisecond
          value: !lambda "return millis();"

external_components:
  - source: github://SzczepanLeon/esphome-components@version_3
    refresh: 0s
    components: [wmbus]

logger:
  level: ${log_level}
  baud_rate: ${log_baudrate}
  logs:
    wmbus: ${log_wmbus}
    wMBus-lib: ${log_wmbus}
    wmbus.unknown: ${log_wmbus}  # Required for log_unknown mode
    sensor: WARN
    sensor.filter: WARN
    text_sensor: WARN
    api.service: ERROR
    json: ERROR
    wifi: WARN
    component: ERROR
    api: WARN

globals:
  - id: boot_counter
    type: int
    restore_value: yes
    initial_value: "0"
  - id: last_value
    type: float
    restore_value: yes
    initial_value: "0.00"
  - id: current_value
    type: float
    restore_value: yes
    initial_value: "0.00"
  - id: hour_value
    type: float
    restore_value: yes
    initial_value: "0.00"
  - id: daily_value
    type: float
    restore_value: yes
    initial_value: "0.00"
  - id: yesterday_value
    type: float
    restore_value: yes
    initial_value: "0.00"
  - id: week_value
    type: float
    restore_value: yes
    initial_value: "0.00"
  - id: lastmonth_value
    type: float
    restore_value: yes
    initial_value: "0.00"
  - id: year_value
    type: float
    restore_value: yes
    initial_value: "0.00"
  - id: send_millisecond
    type: int
    restore_value: false
    initial_value: "0"
  - id: cc1101_state
    type: int
    restore_value: no
    initial_value: "0"
  - id: cc1101_state_message
    type: std::vector<std::string>
    restore_value: no
    initial_value: '{"Init", "Waiting for data", "Data received", "Ready", "Error"}'
  - id: alarm_error_text
    type: std::vector<std::string>
    restore_value: no
    initial_value: '{"No alarm", "General alarm", "Leakage", "Meter blocked", "Back flow", "Underflow", "Overflow", "Submarine", "Sensor fraud", "Mechanical fraud"}'

wifi:
  networks:
    - ssid: !secret wifi_ssid
      password: !secret wifi_password

mdns:
  disabled: false

captive_portal:

ota:
  password: !secret ota_password
  platform: esphome

web_server:
  port: 80
  version: 2

api:
  reboot_timeout: 0s
  services:
    - service: set_watermeter_esp_data
      variables:
        water_val_hour: float
        water_val_day: float
        water_val_yesterday: float
        water_val_week: float
        water_val_year: float
        water_val_lastmonth: float
      then:
        - globals.set:
            id: hour_value
            value: !lambda |-
              if((water_val_hour) and (water_val_hour) > 0.001){ return (water_val_hour); }
              return id(hour_value);
        - globals.set:
            id: daily_value
            value: !lambda |-
              if((water_val_day) and (water_val_day) > 0.001){ return (water_val_day); }
              return id(daily_value);
        - globals.set:
            id: yesterday_value
            value: !lambda |-
              if((water_val_yesterday) and (water_val_yesterday) > 0.001){ return (water_val_yesterday); }
              return id(yesterday_value);
        - globals.set:
            id: week_value
            value: !lambda |-
              if((water_val_week) and (water_val_week) > 0.001){ return (water_val_week); }
              return id(week_value);
        - globals.set:
            id: lastmonth_value
            value: !lambda |-
              if((water_val_lastmonth) and (water_val_lastmonth) > 0.001){ return (water_val_lastmonth); }
              return id(lastmonth_value);
        - globals.set:
            id: year_value
            value: !lambda |-
              if((water_val_year) and (water_val_year) > 0.001){ return (water_val_year); }
              return id(year_value);

time:
  - platform: sntp
    id: time_sntp
    timezone: Europe/Warsaw   # Change to your timezone
    servers:
      - 0.pool.ntp.org
    on_time_sync:
      then:
        - if:
            condition:
              lambda: 'return id(device_lastBoot_time).state == "";'
            then:
              - text_sensor.template.publish:
                  id: device_lastBoot_time
                  state: !lambda return id(time_sntp).now().strftime("%Y-%m-%dT%H:%M:%S %Z");
        - script.execute: set_status_message
    on_time:
      - seconds: 30
        then:
          - script.execute: set_status_message
      - seconds: 0
        minutes: 0
        then:
          - globals.set:
              id: hour_value
              value: "0.00"
          - lambda: id(waterhour).publish_state(id(hour_value));
      - seconds: 0
        minutes: 0
        hours: 0
        then:
          - lambda: |-
              id(yesterday_value) = id(daily_value);
              id(wateryesterday).publish_state(id(yesterday_value));
              id(daily_value) = 0.00;
              id(waterday).publish_state(id(daily_value));
      - seconds: 0
        minutes: 0
        hours: 0
        days_of_week: MON
        then:
          - globals.set:
              id: week_value
              value: "0.00"
          - lambda: id(waterweek).publish_state(id(week_value));
      - seconds: 0
        minutes: 0
        hours: 0
        days_of_month: 1
        months: JAN
        then:
          - globals.set:
              id: year_value
              value: "0.00"
          - lambda: id(wateryear).publish_state(id(year_value));

script:
  - id: set_status_message
    then:
      - lambda: |-
          int msgcode = int(id(cc1101_state));
          std::string message = id(cc1101_state_message)[msgcode];
          id(watermeter_status_message).publish_state(message);

## ------------------------------------------------------------------
## WMBUS — CC1101 pin config (hardware SPI — do not change)
## ------------------------------------------------------------------
wmbus:
  mosi_pin: GPIO13  # D7
  miso_pin: GPIO12  # D6
  clk_pin:  GPIO14  # D5
  cs_pin:   GPIO15  # D8 — 10k pull-down is intentional
  gdo0_pin: GPIO05  # D1
  gdo2_pin: GPIO04  # D2
  log_unknown: true  # Set false after finding your Meter ID
  ## Supported meter types — change type: iperl to match your meter:
  ## WATER:  iperl, izar, itron, apator08, apator162, apatoreitn,
  ##         hydrus, hydrocalm3, multical21, qwater, ultrimis,
  ##         unismart, flowiq2200, rfmtx1, mkradio3, mkradio4, mkradio4a
  ## HEAT:   kamheat, qheat, sharky774, fhkvdataiii, vario451, topaseskr
  ## GAS/E:  amiplus, bmeters, c5isf, compact5, dme07, elf, evo868

switch:
  - platform: template
    name: "${friendly_name} Reset Water Values"
    turn_on_action:
      then:
        - lambda: |-
            id(last_value) = 0.00; id(boot_counter) = 0;
            id(bootcounter).publish_state(id(boot_counter));
            id(current_value) = 0.00; id(watercurrent).publish_state(0);
            id(hour_value) = 0.00; id(waterhour).publish_state(0);
            id(daily_value) = 0.00; id(waterday).publish_state(0);
            id(yesterday_value) = 0.00; id(wateryesterday).publish_state(0);
            id(week_value) = 0.00; id(waterweek).publish_state(0);
            id(lastmonth_value) = 0.00; id(waterlastmonth).publish_state(0);
            id(year_value) = 0.00; id(wateryear).publish_state(0);
  - platform: restart
    name: "${friendly_name} Restart"
    id: restart_switch

sensor:
  - platform: wmbus
    ## -----------------------------------------------------------
    ## Step 1: Flash with 0x00000000 + log_unknown: true
    ## Step 2: Find your ID in log (look for [wmbus:176] line)
    ## Step 3: Fill in ID below, set log_unknown: false, reflash
    ## -----------------------------------------------------------
    meter_id: "0x00000000"  # <-- YOUR METER ID HERE
    type: iperl             # Change for other meter types (see list above)
    key: "E6C88800DEB868C0D6A84880CE982840"
    add_prefix: true

    lqi:
      id: wmbus_cc1101_lqi
      name: "${friendly_name} CC1101 LQI"
      entity_category: "diagnostic"
      unit_of_measurement: "lqi"
      state_class: "measurement"

    rssi:
      id: wmbus_cc1101_rssi

    total_water_m3:
      id: "waterdisplay"
      name: "Water Meter Display"
      unit_of_measurement: "m3"
      state_class: total_increasing
      device_class: "water"
      accuracy_decimals: 3
      icon: mdi:counter
      on_value:
        then:
          - lambda: |-
              if ((id(last_value) > 0.00) and (id(waterdisplay).state) > (id(last_value))) {
                id(cc1101_state) = 2;
                id(current_value) = float(id(waterdisplay).state - id(last_value)) * 1000.00;
                id(watercurrent).publish_state(id(current_value));
                id(hour_value) += id(current_value); id(waterhour).publish_state(id(hour_value));
                id(daily_value) += id(current_value); id(waterday).publish_state(id(daily_value));
                id(week_value) += id(current_value); id(waterweek).publish_state(id(week_value));
                id(year_value) += id(current_value); id(wateryear).publish_state(id(year_value));
              } else {
                id(current_value) = 0.00; id(cc1101_state) = 1;
                id(watercurrent).publish_state(id(current_value));
              }
              id(last_value) = id(waterdisplay).state;
          - text_sensor.template.publish:
              id: watermeter_lastupdate
              state: !lambda return id(time_sntp).now().strftime("%Y-%m-%dT%H:%M:%S %Z");
          - sensor.template.publish:
              id: watermeter_read_timeout
              state: !lambda |-
                int time_used = (millis() - id(send_millisecond));
                id(send_millisecond) = millis();
                return float(time_used) / 1000;
          - script.execute: set_status_message
          - binary_sensor.template.publish:
              id: statusled
              state: !lambda "return id(current_value) > 0;"

    last_month_total_water_m3:
      name: "Water Meter Last Month Display"
      id: "waterdisplay_lastmonth"
      unit_of_measurement: "m3"
      state_class: total_increasing
      device_class: "water"
      accuracy_decimals: 3

    current_month_total_water_l:
      name: "Water Month"
      id: "watermonth"
      accuracy_decimals: 2
      unit_of_measurement: "L"
      state_class: total_increasing
      device_class: "water"

    remaining_battery_life_y:
      name: "Water Meter Battery Life"
      id: "watermeter_batterie"
      accuracy_decimals: 2
      unit_of_measurement: "years"
      entity_category: "diagnostic"
      icon: mdi:battery

    transmit_period_s:
      name: "Water Meter Transmit Interval"
      id: "watermeter_transmit_periode"
      unit_of_measurement: "s"
      accuracy_decimals: 0
      entity_category: "diagnostic"
      icon: mdi:timelapse

    current_alarms:
      id: "watermeter_current_alarms"
      name: "Water Meter Alarm Code"
      entity_category: "diagnostic"
      on_value:
        then:
          - lambda: |-
              int error_code = int(x);
              std::string message = id(alarm_error_text)[error_code];
              id(watermeter_alarm_message).publish_state(message);
              if(error_code != 0){
                id(watermeter_alarm_timestamp).publish_state(
                  id(time_sntp).now().strftime("%Y-%m-%dT%H:%M:%S %Z").c_str());
              }

    previous_alarms:
      id: "watermeter_previous_alarms"
      name: "Water Meter Previous Alarm Code"
      entity_category: "diagnostic"
      on_value:
        then:
          - lambda: |-
              int error_code = int(x);
              id(watermeter_alarm_perv_message).publish_state(id(alarm_error_text)[error_code]);
              if(!id(watermeter_alarm_timestamp).has_state())
                id(watermeter_alarm_timestamp).publish_state("--");

  - platform: template
    name: "Water Current"
    id: "watercurrent"
    accuracy_decimals: 2
    unit_of_measurement: "L"
    state_class: "measurement"
    device_class: "water"
    lambda: return (id(current_value));
  - platform: template
    name: "Water Hour"
    id: "waterhour"
    accuracy_decimals: 2
    unit_of_measurement: "L"
    state_class: total_increasing
    device_class: "water"
    lambda: return (id(hour_value));
  - platform: template
    name: "Water Today"
    id: "waterday"
    accuracy_decimals: 2
    unit_of_measurement: "L"
    device_class: "water"
    state_class: total_increasing
    lambda: return (id(daily_value));
  - platform: template
    name: "Water Yesterday"
    id: "wateryesterday"
    accuracy_decimals: 2
    unit_of_measurement: "L"
    device_class: "water"
    state_class: total_increasing
    lambda: return (id(yesterday_value));
  - platform: template
    name: "Water Week"
    id: "waterweek"
    accuracy_decimals: 2
    unit_of_measurement: "L"
    device_class: "water"
    state_class: total_increasing
    lambda: return (id(week_value));
  - platform: template
    name: "Water Year"
    id: "wateryear"
    accuracy_decimals: 2
    unit_of_measurement: "L"
    state_class: total_increasing
    device_class: "water"
    lambda: return (id(year_value));
  - platform: template
    name: "Water Last Month"
    id: "waterlastmonth"
    accuracy_decimals: 2
    unit_of_measurement: "L"
    state_class: total_increasing
    device_class: "water"
    lambda: return (id(lastmonth_value));
  - platform: template
    name: "Water Meter Data Interval"
    id: watermeter_read_timeout
    icon: mdi:clock-start
    accuracy_decimals: 1
    unit_of_measurement: "s"
    state_class: "measurement"
    entity_category: "diagnostic"
  - platform: wifi_signal
    id: wifi_signal_db
    update_interval: 60s
    internal: true
    disabled_by_default: true
  - platform: copy
    source_id: wifi_signal_db
    name: "${friendly_name} WiFi Quality"
    filters:
      - lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
    unit_of_measurement: "%"
    entity_category: "diagnostic"
  - platform: copy
    source_id: wmbus_cc1101_rssi
    name: "${friendly_name} CC1101 Signal Quality"
    filters:
      - lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
    unit_of_measurement: "%"
    entity_category: "diagnostic"
  - platform: uptime
    name: "${friendly_name} Uptime"
    id: uptime_human
    filters:
      - lambda: return x / 3600;
    unit_of_measurement: "h"
    entity_category: "diagnostic"
    state_class: "measurement"
    accuracy_decimals: 2
  - platform: template
    name: "${friendly_name} Boot Counter"
    id: bootcounter
    icon: mdi:counter
    accuracy_decimals: 0
    state_class: "measurement"
    entity_category: "diagnostic"
    lambda: return (id(boot_counter));

binary_sensor:
  - platform: template
    name: "Water Meter Status LED"
    id: statusled
    icon: mdi:water
    entity_category: "diagnostic"
    lambda: "return id(current_value) > 0;"

text_sensor:
  - platform: template
    name: "Water Meter Status"
    id: watermeter_status_message
    icon: mdi:information
    entity_category: "diagnostic"
  - platform: template
    name: "Water Meter Alarm"
    id: watermeter_alarm_message
    icon: mdi:alarm-light
    entity_category: "diagnostic"
  - platform: template
    name: "Water Meter Previous Alarm"
    id: watermeter_alarm_perv_message
    icon: mdi:alarm-light
    entity_category: "diagnostic"
  - platform: template
    name: "Water Meter Alarm Time"
    id: watermeter_alarm_timestamp
    icon: mdi:clock-alert
    entity_category: "diagnostic"
  - platform: version
    name: "${friendly_name} ESPHome Version"
    id: appver
    disabled_by_default: true
  - platform: template
    name: "${friendly_name} Last Boot"
    disabled_by_default: true
    id: device_lastBoot_time
    icon: mdi:clock-start
  - platform: template
    name: "${friendly_name} Last Update"
    id: watermeter_lastupdate
    icon: mdi:clock-check
    entity_category: "diagnostic"
  - platform: template
    id: systime
    entity_category: "diagnostic"
    internal: true
    disabled_by_default: true
    lambda: return id(time_sntp).now().strftime("%Y-%m-%dT%H:%M:%S %Z");
  - platform: template
    id: watermeterdata
    internal: true
    disabled_by_default: true
    lambda: |-
      char buf[128];
      sprintf(buf, "%.3f|%.3f|%.3f|%.3f|%.3f|%.3f|%.3f|%.3f|%.3f|%s",
             id(waterdisplay).state, id(current_value), id(hour_value),
             id(daily_value), id(yesterday_value), id(week_value),
             id(watermonth).state, id(lastmonth_value), id(year_value),
             id(systime).state.c_str());
      std::string s = buf;
      return s;

Step 5 — Flashing and reading the log

1

Connect NodeMCU via USB to a computer running Chrome or Edge
2

In ESPHome Dashboard: three dots next to your device → Install → Plug into this computer
3

Wait for compilation (~2–5 min first time) and flashing. After reboot the device connects to WiFi and appears in Home Assistant.
4

Open Logs in ESPHome Dashboard to see incoming telegrams. Temporarily set log_level: "VERY_VERBOSE" for this step.
Phase 1 — Discovering the Meter ID (meter_id: 0x00000000)
[10:02:50][V][rxLoop:167]: Have 56 bytes from CC1101 Rx, RSSI: -56 dBm LQI: 128
[10:02:50][D][mbus:034]: Processing T1 A frame
[10:02:50][V][crc:031]:     calculated: 0x5FCB, read: 0x5FCB  <-- Block1 OK
[10:02:50][V][crc:031]:     calculated: 0x38CD, read: 0x38CD  <-- Block2 OK
[10:02:50][V][crc:031]:     calculated: 0xB521, read: 0xB521  <-- Block3 OK
[10:02:50][D][wmbus:176]: Meter ID [0x20863703] RSSI: -56 dBm LQI: 128
                                    ^^^^^^^^^^^
                          Copy this value to meter_id in your YAML
                          "not found in configuration" at this stage is normal
Once you have the ID: fill it in as meter_id: "0x20863703", set log_unknown: false, and reflash via OTA (no USB needed). Then wait — the interval may be 10–30 minutes.
Phase 2 — Working reception (Meter ID configured)
[14:02:52][V][rxLoop:167]: Have 56 bytes from CC1101 Rx, RSSI: -50 dBm LQI: 128
[14:02:52][D][mbus:034]: Processing T1 A frame
[14:02:52][V][crc:031]:     calculated: 0x5FCB, read: 0x5FCB  <-- Block1 OK
[14:02:52][V][crc:031]:     calculated: 0x5C7E, read: 0x5C7E  <-- Block2 OK
[14:02:52][V][crc:031]:     calculated: 0x3A78, read: 0x3A78  <-- Block3 OK
[14:02:52][D][wmbus:090]: Using driver 'iperl' for ID [0x20863703] RSSI: -50 dBm
                                       ^^^^^^^
                                  driver matched -- meter type recognised
[14:02:52][V][utils:291]: 2F2F check after decrypting - OK
                                                         ^^
                             AES key correct -- most important confirmation line
[14:02:52][VV][drivers:253]: Found register '0413' with '836236'->'836.236000'
[14:02:52][V][wmbus:121]: Publishing 'total_water_m3' = 836.2360
                                                         ^^^^^^^^^
                                  value sent to Home Assistant
Key lines explained:
[rxLoop:167]

CC1101 received a radio frame. RSSI -50 dBm is excellent signal.
[mbus:034]

T1 A frame — transmission mode used by iPerl. Correct frequency confirmed.
[crc:031]

CRC validation — iPerl sends 3 data blocks, each with its own CRC. All three must match.
[wmbus:090]

Driver matched — only appears after the correct Meter ID is configured.
[utils:291]

2F2F check OK — the most important line. AES key correct, telegram decrypted. If missing: wrong key.
[wmbus:121]

Value published to HA — entity changes from unknown to real reading.

Not using iPerl? 30 meter types supported

The wmbus component supports 30 different wMBus meter types. Just change type: iperl to the correct type for your meter:
 Water meters
iperl
izar
itron
apator08
apator162
apatoreitn
hydrus
hydrocalm3
multical21
qwater
ultrimis
unismart
flowiq2200
rfmtx1
mkradio3
mkradio4
mkradio4a
 Heat and cooling meters
kamheat
qheat
sharky774
fhkvdataiii
vario451
topaseskr
 Gas and electricity meters
amiplus
bmeters
c5isf
compact5
dme07
elf
evo868
Full and up-to-date driver list: github.com/SzczepanLeon/esphome-components

What’s next — Part 3

The device is running and sending data to Home Assistant. In Part 3 we build the HA dashboard — consumption graphs, daily and weekly charts, leak detection alerts, and billing statistics.
Source code on GitHub:
Complete firmware and instructions at github.com/marklabspl

Społeczność MarkLabs

Dyskutuj na forum

Pytania, doświadczenia i rozwiązania do tego artykułu publikujemy teraz na forum MarkLabs.

Otwórz dyskusję na forum

Wymagane jest bezpłatne konto MarkLabs. Dotychczasowe komentarze bloga nie są przenoszone.

buymeacoffee.com