Raspberry Pi čtení dat z teploměru QINGPING Temperature & RH monitor, M version – Xiaomi mi

Pojďme si ukázat jak číst teplotu a vlhkost z e-link teploměru a vlhkoměru QINGPING Temperature & RH monitor, M version

Čtení hodnot z Android zařízení

Do telefonu stáhněte aplikaci Xiaomi Home z Google Play. Na teploměru podržíte zadní tlačítko několik vteřin aby na displeji začala blikat/svítit ikonka bluetooth. Pak v aplikaci dáte vyhledat nové zařízení a objeví se vám dostupné teploměry. Pak postupujete podle instrukcí

Čtení hodnot z Raspberry Pi

Aby bylo možné číst teplotu z RaspBerryPi je potřeba v teploměru upravit firmware – tím nebude možné se na teploměr připojit z Android telefonu (viz bod výše)!

Úpravu firmwate provede podle: https://github.com/pvvx/ATC_MiThermometer

Úprava firmware probíhá bezdrátově přes bluetooth – není potřeba nic stahovat a speciální znalosti. Stačí notebook s bluetooth. Původní firmware je možné nahrát zpět.

Aktualizaci provedet vybráním požadovaného teploměru a klikem na tlačítko OTA:

Na notebooku zapněte Blutooth

  1. Jděte na stránku https://github.com/pvvx/ATC_MiThermometer vyberte teploměr a klikněte na OTA
  2. Několik vteřin podržte zadní tlačítko aby blikala bluetooth ikona
  3. Vstupní pole „BLE device name prefix filter(s):“ můžete nechat prázdné. Tlačítkem „connect“ spustíte prohledávání bluetoth zařízení. Musíte tam najít váš „QINGPING Temp RH M“ se kterým se spárujete. Je potřeba chvilku počkat aby se zobrazil další formulář s tlařítkem „Do Activation“
  4. Tlačítkem „Do Activation“ provedete změnu firmware
  5. Po několika vteřinách skočí do polí „Device known id“, „Mi token“, „Mi bind key“ hodnoty, nahoře na stránce se zobrazí aktuální teplota a vlkost.
  6. vyberete firmwer (tady můžete nahrát i originální) – já vybral CGG1M_V48.bin
  7. Tlačítkem „Start Flashing“ provedete změnu firmware

Před aktualizací firmware se teploměr jmenoval „Qingping Temp RH M“ a po aktualizaci se jmenoval „CGG_83F48D“

Připojujeme se z Raspberry Pi

  1. instalce nezbytných nástrojů
sudo apt-get update
sudo apt-get install bluez python3-pip
sudo pip3 install bluepy

2. zjištění MAC adresy teploměru

sudo hcitool lescan

Vypíše se seznam BLE zařízení, mezi nimi hledejte název CGD_XXXXXX.

3. python script pro čtení teploty

V tomto scriptu stačí nastavit správnou MAC adresu

from bluepy.btle import Peripheral

# Nahraď MAC adresu adresou svého teploměru
MAC_ADDRESS = "83:F4:8D:XX:XX:XX"

def read_temperature(mac):
    try:
        # Připojení k teploměru
        device = Peripheral(mac)

        # Čtení dat ze specifického UUID (např. pro teplotu)
        characteristics = device.getCharacteristics(uuid="00002a6e-0000-1000-8000-00805f9b34fb")
        if characteristics:
            temperature_data = characteristics[0].read()
            # Konverze získaných dat na teplotu (pokud je třeba)
            temperature = int.from_bytes(temperature_data, byteorder='little', signed=True) / 100
            return temperature

        device.disconnect()

    except Exception as e:
        print(f"Error: {e}")
        return None

temperature = read_temperature(MAC_ADDRESS)
if temperature is not None:
    print(f"Teplota: {temperature} °C")
else:
    print("Nelze získat teplotu.")

Script sputíme příkazem:

ubuntu@ubuntu:~$ python3 temperature.py
Teplota: 21.65 °C

C# serializace a deserilizace výčtového typu

V C# se při serializaci a deserializaci JSON velmi často potřebujeme vypořádat s výčtovými typy (enum). Ve výchozím nastavení je hodnota z výčtového typu interpretována jako celé číslo – to většinou nestačí, protože požadujeme textovou hodnotu. Pojďme si ukázat, jak to vyřešit nativní knihovnou System.Text.Json a knihovnou Newtonsoft.Json

public class Student
{
    public string Name { get; set; }
    public SexEnum Sex { get; set; }

}

public enum SexEnum 
{
    Female, Male
}

var student1 = new Student() { Name = "Pepek Vyskoc", Sex = SexEnum.Male }

// Native serialize
JsonSerializer.Serialize(student1);

// Newtonsoft
return JsonConvert.SerializeObject(student1);

Vrátí json:

{
  "Name": "Pepek Vyskoc",
  "Sex": 1
}

Funkční ale dost často nedostačující, protože z pohlaví 0 a 1 toho moc nepoznáme.

Serializace enum jako textový řetězec

Stačí přidat k požadované propertě anotaci *EnumConverter:

// Native
public class Student
{
    ...
    [JsonConverter(typeof(JsonStringEnumConverter))]
    public SexEnum Sex { get; set; }
    ...
}
// Newtonsoft
public class Student
{
    ...
    [JsonConverter(typeof(StringEnumConverter))]
    public SexEnum Sex { get; set; }
    ...
}

Kde získáme požadovaný formát odpovědi:

{
  "Name": "Pepek Vyskoc",
  "Sex": "Male"
}

Globální serializace enum jako textový řetězec

Pokud nechcete před každou propertu uvádět anotaci pro converter, máte možnost ji nastavit globálně do souboru Program.cs:

// Native
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
    });

// Newtonsoft
builder.Services.AddControllers()
    .AddNewtonsoftJson(options =>
    {
        options.SerializerSettings.Converters.Add(new StringEnumConverter());
    });

Tím dosáhneme požadovaného výsledku automaticky

Linux – připojení přes SSH klíč

Doba pokročila, přihlašování na server přes jméno a heslo není nejbezpečnější a je zbytečně zdlouhavé. Nyní si v cloudu vytvoříte server na pár kliknutí a následně se na něj přihlásíte přes SSH klíč. Je to bezpečné a rychlé.

Jak to funguje

Potřebujete vygenerovat soukromý a veřejný klíč. Soukromý klíč umístíte na klienta, ze kterého se přihlašujete a veřejný klíč na server, na který se přihlašujete. Při inicializaci spojení vám server pošle data, která zašifrujete soukromým klíčem, a server po rozšifrování veřejným klíčem získá původní data. Tím ověří, že máte správný soukromý klíč a povolí vám přístup.

Soukromý klíč v žádném případě nesmíte nikomu poskytnout, ten si chraňte!

K veřejnému klíči se může dostat kdokoliv. V případě napadení serveru, není problém když se útočník dostane k veřejnému klíči.

Vygenerování klíčů

Pojďme vygenerovat soukromý a veřejný klíč – to většinou budeme dělat na klientu.

ssh-keygen -t rsa

Výstup bude podobný tomuto -toto není výstup pro klíč, který používám :-):

root@vencax-virtual-machine:/home/venca-x# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa
Your public key has been saved in /root/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:wV81a776hOaU5Gtj5vVtWhujL2hUJn53H4XsdL3dG72 root@vencax-virtual-machine
The key's randomart image is:
+---[RSA 3072]----+
| .+,G|
| +.PRX|
| =oxR|
| . . --A|
| S . l.x+|
| .+. =E+|
| .+.F.o=.|
| .o.- .|
| .=a. |
+----[SHA256]-----+

Budete vyzváni, zda se má veřejný klíč uložit do výchozího umístění (/root/.ssh/id_rsa) – stačí potvrdit <ENTER>

Dále budete vyzváni pro zadání passphrase (hesla k certifikátu). Toto heslo není povinné. nicméně doporučuji jeho zadání pro případ kdyby se někdo dostal k privátnímu klíči.

Tím se klíče uloží do umístění: /root/.ssh/

  • id_rsa – privátní klíč
  • id_rsa.pub – soukromý klíč

Nahrání veřejného klíče na server

Klientská část je hotova. Nyní nahrajeme veřejný SSH klíč na server, ke kterému se budeme připojovat. Můžeme nahrát stejný veřejný klíč na všechny servery, na které se chceme připojit.

ssh-copy-id -i ~/.ssh/id_rsa.pub user@host.com

Ukázka výstupu:

root@vencax-virtual-machine:~/.ssh# ssh-copy-id -i ~/.ssh/id_rsa.pub user@host.com
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
user@host.com's password:

Number of key(s) added: 1

Now try logging into the machine, with: "ssh 'user@host.com'"
and check to make sure that only the key(s) you wanted were added.

Na serveru se podívejte do souboru .ssh/authorized_keys, ve kterém byste měli vidět přidaný veřejný klíč z klienta

Zapnutí autentizace přes SSH klíče na serveru

Na serveru nyní zapneme přihlášení přes SSH klíč a zakážeme přihlášení přes jméno a heslo. To provedeme v souboru:

vim /etc/ssh/sshd_config

Povolení přihlášení přes SSH klíč:

RSAAuthentication yes
PubkeyAuthentication yes

Zakázání přihlášení přes SSH přes jméno a heslo:

ChallengeResponseAuthentication no
PasswordAuthentication no
UsePAM no
PermitRootLogin no

Nakonec restartujeme SSH:

systemctl restart sshd.service
Tím máme hotovo. Restartem SSH stále zůstáváme připojení k serveru, než otestujete správnou funkčnost přes SSH klíče, se raději neodpojujte :-)

Putty – připojení přes SSH klíč

Připojení z linuxu nám funguje, trochu problém nastává u připojení přes Putty. Nyní máme soukromý klíč ve formátu OpenSSH a musíme ho převést na .ppk

Spustíme program PuTTYgen – už je předinstalovaná ve WIndows 10?

Do programu PuTTYgen naimportujeme náš soukromý klíč (id_rsa) File -> Load private key
Načtený soukromý klíč uložíme tlačítkem Save private key -> například jako id_rsa.ppk

Tento výsledný id_rsa.ppk vložíme k našemu připojení v Putty: Connection -> SSH -> Auth -> Private key for authentication

Dnes jsme si ukázali bezpečnější, rychlejší a modernější způsob přihlášení na server přes SSH. Už se nemusíte bát o svá hesla, jejich pravidelnou změnu a brutal force útok pro prolomení hesla.

Npm a Forever: automatické spuštění aplikace

Forever je jednoduchý nástroj, který zajišťuje nepřetržitý běh daného skriptu. Pokud restatujete server, nebo aplikace spadne, forever se postará o opětovné spuštění.

Nainstalujte forever globálně přes NPM:

npm install forever -g

forever.json

Tento soubor vytvoříme do node projektu, který chceme spouštět. Pokud máte projekt umístění na: /var/www/nodes/project vytvoříme soubor: /var/www/nodes/forever.json

[
  {
    "uid": "appName1",
    "append": true,
    "watch": true,
    "script": "index.js",
    "sourceDir": "/var/www/nodes/project/",
    "workingDir": "/var/www/nodes/project/"
  }
]

Automatické spuštění foreveru pomocí služby cron

Do cron souboru přidáme následující řádek:

crontab -e
@reboot /usr/local/bin/forever start /var/www/nodes/forever.json > /dev/null 2>&1

Monitoring forever

Seznam spuštěných aplikací:

forever list

Zastavení konkrétní aplikace:

forever stop uid

Zastavení všech aplikací:

forever stopall

Zastavení logu:

forever logs 0

Honneywell Dolphin 75e

Do práce jsme vybírali mobilní terminál, který bude mít hardwarovou čtečku čárových kódu. Po prozkoumání nabízených zařízení nám zůstaly pouze zařízení s OS Android (snad s tím W10 ještě zahejbe ale asi to potrvá). Nakonec jsme vybrali Honneywell Dolphin 75e ale pro ten nefungují oficiální ovladače. WTF?

Nakonec jsem to obešel takto a ovladače fungují:

  1. přesvědčte se že máte nainstalovány ovladače pro Google USB Driver
    doolphin75e_1
  2. Úprava android_winusb.inf
    Soubor android_winusb.inf jsem v mém případě nalezl na: C:\Users\pc-x\AppData\Local\Android\sdk\extras\google\usb_driver\android_winusb.infProvedeme jeho editaci a za sekce Under both the [Google.NTx86] [Google.NTamd64] přidáme:

    ;Honeywell Dolphin Android Product[A0:fastboot,A1:adb,A2:UMS,A3:ums-adb]
    %SingleAdbInterface% = USB_Install, USB\VID_0C2E&PID_0BA0&MI_00
    %SingleAdbInterface% = USB_Install, USB\VID_0C2E&PID_0BA1
    %CompositeAdbInterface% = USB_Install, USB\VID_0C2E&PID_0BA3&MI_01
    %SingleBootLoaderInterface% = USB_Install, USB\VID_0C2E&PID_0BA0
    
  3. Ve Správci zařízení zvolíme na neznámém zařízení Aktualizace software ovladače… a vybereme Vyhledat ovladač v počítači kde zvolíme cestu:
    C:\Users\pc-x\AppData\Local\Android\sdk\extras\google\usb_driver

    vyskočí upozornění, že Windows nemůže oveřit vydavatele tohoto software, to potvrdíme a ovladače máme nainstalované 🙂

ADB

Nyní když máme ovladače, můžeme použít adb příkazy.

adb shell
adb devices

 

Mikrotik – aktualizace firmware

Jak se připojit do Mikrotiku

Máme několik možností jak se do Mikrotiku přihlásit (seriová linka, telnet, SSH, webové rozhraní, …) My si dnes ukážeme přihlášení přes Winbox.

Stáhneme Winbox – jedná se o .exe soubor, který se neinstaluje – pouze se spustí.

Winbox po spuštění vypadá takto:

mikrotik-1

Automaticky dojde k vyhledání všech Mikrotiků na síti a zobrazení základních informací. Dvojklikem vybereme Mikrotik do kterého se chceme přihlásit, tím se načte do horní části okna. Zadáme login a heslo. Kliknutím na tlačítko Connect proběhne připojení.

Defaultní nastavení přístupových údajů pro Mikrotik v továrním nastavení:

login: admin
password: je prázdné

Základy práce s Winboxem

Po úspěšném připojení do Mikrotiku se otevře následující okno:

mikrotik-2

Všimněte si záhlaví okna, kde jsou důležité informace:

Vidíme na jakého uživatele a na jakém Mikrotiku jsme připojeni: admin@192.168.88.1
Název Mikrotiku: rozostřeno
Aktuální verzi RouterOS: 5.2.4
A typ zařízení: RB532 (mipsle)

Pokud chceme aktualizovat firmware, musíme stáhnou správný RouterOS pro náš typ.

Stažení RouterOS

Již víme jaké zařízení máme ( RB532 (mipsle) ), můžeme se poohlédnou po RouterOS.Jak jinak než na oficiálních stránkách Mikrotiku kde je sekce Download.

mikrotik-4

Vybereme požadovanou verzi. Aktuálně je poslení verze 6.33. Nyní je potřeba dávat pozor, jelikož sekce mipsle je v seznamu 2x a musíte správně vybrat podle vašeho typu Mikrotiku! Do PC stáhneme Main package (cca 12MB).

Záloha Mikrotiku přes Winbox

Před aktualizací si udělejte zálohu stávajícího nastavení. V menu vybereme Files a klikneme na tlačítko Backup.

mikrotik-5

Vznikne nový soubor, který přes schránku (nahoře v okně Files je ikona Copy) zkopírujeme do PC.

Aktualizace firmware na Mikrotiku přes Winbox

Nyní můžeme nainstalovat stažený Main package balíček. V mém případě má balíček takovýto název: routeros-mipsle-6.33.npk

Tento soubor nahrajeme do sekce Files (přetažením do otevřeného okna Files). Následně v menu vybereme System -> Reboot a Mikrotik si automaticky nahraje tento nový firmware.

PHP čtení dat z Google Analytics

Dnes si ukážeme postup jak se z PHP s Analytics API připojit na Google Analytics a získat data.

1) Aktivace Analytics API

Abychom mohli začít používat Google Analytics API, musíme vytvořit nový projekt v Google Developers Console a povolit API. Přímý odkaz na vytvoření nového projektu v Google Developer Console a aktivace Google Analytics API

Případně můžete aktivovat rozhraní API Google Analytics v Developer konzoli následujícím způsobem:

V menu vybereme: APIs & auth -> APIs. Vyhledáme Analytics API a ektivujeme tlačítkem Enable API.

2) Vytvoření client ID

Aby se bylo možné připojit na API, musíme vytvořit uživatele pod kterým se budeme přihlašovat. Uděláme to v sekci: APIs & auth -> Credentials kde vytvoříme nový Service accoun.

Klikneme na modré rozbalovací tlačítko Add credentials a vybereme Service account. Nově vytvořený uživatel se nebude přihlašovat heslem ale klíčem. KEY TYPE zvolíme volbu na P12.

ga-create-service-account-p12

Po vytvoření se nám stáhne klíč pro přihlášení (project-xxxxxxxxxx.p12) a vytvoří uživatel s podobným e-mailem: xxxxxxxxxxxxxxxxxxxx@developer.gserviceaccount.com

Oboje údaje jsou velice důležité a dobře si je uložte. Budeme je potřebovat, protože se přes něj budeme v PHP hlásit k Analytics API 🙂

3) Přidání účtu do Google Analytics

Přes účet v bodu 2 se budeme hlásit k API a získávat data. Proto tedy nově vytvořený účet přidáme k požadovanému profilu v Google Analytics. Po přihlášení vybereme v horním pruhu položku Správce. Ve sloupci SLUŽBA (prostřední sloupec) vybereme požadovanou službu a klikneme na Správa uživatelů. Přidáme nového uživatele: Do pole Přidat oprávnění pro uživatele: přidáme vytvořený email (v mém případě: xxxxxxxxxxxxxxxxxxxx@developer.gserviceaccount.com) a ponecháme oprávnění: Číst a analyzovat.

4) Napojení na Analytics API z PHP

Stáhneme knihovnu google-api-php-client: https://github.com/google/google-api-php-client

Knihovnu je také možné stáhnout přes composer:

composer require google/apiclient

Použijeme tento ukázkový kód, který zobrazuje počet návštěv za posledních 7 dní. Stačí pouze změnit tyto hodnoty: ZDE_ZADEJTE_EMAIL_VYTVOŘENÝ_V_KROKU_2 a ZDE_ZADEJTE_KLÍČ_VYTVOŘENÝ_V_KROKU_2

<?php

function getService()
{
  // Creates and returns the Analytics service object.

  // Load the Google API PHP Client Library.
  require_once 'google-api-php-client/src/Google/autoload.php';

  // Use the developers console and replace the values with your
  // service account email, and relative location of your key file.
  $service_account_email = 'ZDE_ZADEJTE_EMAIL_VYTVOŘENÝ_V_KROKU_2';
  $key_file_location = 'ZDE_ZADEJTE_KLÍČ_VYTVOŘENÝ_V_KROKU_2.p12>';

  // Create and configure a new client object.
  $client = new Google_Client();
  $client->setApplicationName("HelloAnalytics");
  $analytics = new Google_Service_Analytics($client);

  // Read the generated client_secrets.p12 key.
  $key = file_get_contents($key_file_location);
  $cred = new Google_Auth_AssertionCredentials(
      $service_account_email,
      array(Google_Service_Analytics::ANALYTICS_READONLY),
      $key
  );
  $client->setAssertionCredentials($cred);
  if($client->getAuth()->isAccessTokenExpired()) {
    $client->getAuth()->refreshTokenWithAssertion($cred);
  }

  return $analytics;
}

function getFirstprofileId(&$analytics) {
  // Get the user's first view (profile) ID.

  // Get the list of accounts for the authorized user.
  $accounts = $analytics->management_accounts->listManagementAccounts();

  if (count($accounts->getItems()) > 0) {
    $items = $accounts->getItems();
    $firstAccountId = $items[0]->getId();

    // Get the list of properties for the authorized user.
    $properties = $analytics->management_webproperties
        ->listManagementWebproperties($firstAccountId);

    if (count($properties->getItems()) > 0) {
      $items = $properties->getItems();
      $firstPropertyId = $items[0]->getId();

      // Get the list of views (profiles) for the authorized user.
      $profiles = $analytics->management_profiles
          ->listManagementProfiles($firstAccountId, $firstPropertyId);

      if (count($profiles->getItems()) > 0) {
        $items = $profiles->getItems();

        // Return the first view (profile) ID.
        return $items[0]->getId();

      } else {
        throw new Exception('No views (profiles) found for this user.');
      }
    } else {
      throw new Exception('No properties found for this user.');
    }
  } else {
    throw new Exception('No accounts found for this user.');
  }
}

function getResults(&$analytics, $profileId) {
  // Calls the Core Reporting API and queries for the number of sessions
  // for the last seven days.
   return $analytics->data_ga->get(
       'ga:' . $profileId,
       '7daysAgo',
       'today',
       'ga:sessions');
}

function printResults(&$results) {
  // Parses the response from the Core Reporting API and prints
  // the profile name and total sessions.
  if (count($results->getRows()) > 0) {

    // Get the profile name.
    $profileName = $results->getProfileInfo()->getProfileName();

    // Get the entry for the first entry in the first row.
    $rows = $results->getRows();
    $sessions = $rows[0][0];

    // Print the results.
    print "First view (profile) found: $profileName\n";
    print "Total sessions: $sessions\n";
  } else {
    print "No results found.\n";
  }
}

$analytics = getService();
$profile = getFirstProfileId($analytics);
$results = getResults($analytics, $profile);
printResults($results);

 

WooCommerce: získání všech tagů a kategorií

Poslední dobou dělám věci okolo WordPressu a Woocommerce. Dnes si ukážeme jak v doplňku získávám všechny kategorie a tagy.

Jak získat všechny tagy?

Function Reference/get terms

$taxonomies = 'product_tag';
$args = array(
   'taxonomy'     => 'product_cat',
   'hide_empty'   => 0
);
$terms = get_terms($taxonomies, $args);
foreach ($terms as $term) {
   //var_dump($term);
   //$termLink = get_term_link( $term );
   echo $term->name;
}

 

Jak získat všechny kategorie?

Function Reference/get categories

$args = array(
   'taxonomy'     => 'product_cat',
   'hide_empty'   => 0
);
$categories = get_categories( $args );
foreach( $categories as $category ) {
   //var_dump($category);
   //$categoryLink = get_category_link( $category );
   echo $category->name;
}