GithubHelp home page GithubHelp logo

asksinpp's People

Contributors

alexreinert avatar bird968 avatar darkshortie avatar der-pw avatar feinfinger380 avatar harvey637 avatar henrywiechert avatar hmsteve avatar jp112sdl avatar krikk avatar manawyrm avatar maniac103 avatar mdk2412 avatar messemar avatar nico9n avatar p2122 avatar pa-pa avatar psi-4ward avatar scuba82 avatar stan23 avatar tommajor avatar trilu2000 avatar xento avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

asksinpp's Issues

Weather.h BIDI + sendBroadcast

Hi,

in https://github.com/pa-pa/AskSinPP/blob/master/Weather.h#L22 wird das BIDI Flag gesetzt wobei
in https://github.com/pa-pa/AskSinPP/blob/master/Weather.h#L44 ein broadcastEvent() verschickt wird. Hier gibt also BIDI keinen Sinn oder?

Sollten wir nicht die Implementierung von Tom:
https://github.com/TomMajor/SmartHome/blob/master/HB-UNI-Sensor1/HB-UNI-Sensor1.ino#L323
adaptieren und zumindest ca einmal pro Tag an sendPeerEvent() schicken?

Somit würden auch eventuelle Config-Daten übertragen werden was aktuell nur per Config-Press möglich ist.

Low-Bat.-Schwelle nur 5-15Volt

Hallo
ich nutze HM-LC-SW1-BA-PCB.ino und möchte die Hardware mit 2 Batterien betreiben.
also mit 3,3 Volt und niedriger. In der CCU2 lässt sich die Low-Bat.-Schwelle nur im Bereich 5-15Volt einstellen. Dadurch habe ich eine Fehlermeldung in der CCU und kann keine sinnvolle Warnung unter 3,3 Volt einstellen. Gibt es eine Möglichkeit das zu ändern? Wenn ja was müsste ich ändern?
Gruß
Christof

misleading DEVID in makeota.sh (should be DEVMODEL)

Hi using this issue to ask for correction of README.md and makeota?.sh, makeota.html

Ifi I check the wording and meaning of the 4 items, that are written at the end of bootloader I find
in device.h:
#define OTA_CONFIG_START 0x7fe0 // start address of 16 byte config data in bootloader
#define OTA_MODEL_START 0x7ff0 // start address of 2 byte model id in bootloader
#define OTA_SERIAL_START 0x7ff2 // start address of 10 byte serial number in bootloader
#define OTA_HMID_START 0x7ffc // start address of 3 byte device id in bootloader

When I look into makeota*.sh I find:
DEVID ... written to 0x7ff0, which is named OTA_MODEL_START, 2 bytes is correct
HMID ... written to 0x7ffc0, which is named OTA_HMID_START, 3 bytes is correct
SERIAL ... written to 0x7ff2, which is named OTA_SERIAL_START, 10 bytes is correct

What BUGS me is that in other parts of asksin

  • HMID is synonym to (DeviceInfo) // Device ID.
  • DEVID is synonym to (DeviceInfo) // Device model

The usage of DEVID (sounds like device id to me) ist NOT equal // Device Id from DeviceInfo struct.
Which leads to confusion :-(

Proposal:
replace DEVID in makeota*.sh to DEVMODEL, errmsg should read "Wrong Device Model: 2 Byte (hex) expected"

correct type: exprected -> expected

explain usage (meaning) of DEVMODEL, what is it good for?

adopt README.md and makeota.html accordingly

Thank You!

Pairing mit HM-Sec-Cen nicht möglich

Hallo!

Leider lassen sich die nachgebauten Komponenten (u.a. HM-RC-P1) nicht an der Alarmzentrale (HM-Sec-Cen) anlernen. Habe auch die drei Zeilen mit #define aes ... versucht. Mit CCU2 oder Homegear gibt es keine Probleme. Ein Pairing mit einem originalen HM-PBI-4-FM oder HM-Sec-Mdir ist möglich.
Grüße,
Tobias

Basic Module for sending 32 bit word

Hey!
I am looking to build a low power sensor using Arduino Pro Mini and a CC1101 module.
All I need to do is to be able to send and receive a 32bit datagram using fhem.
Can you help me with that?

Best

Recreating HM-RC-Key4-2

Hey there,

I am trying to recreate HM-RC-Key4-2 and peer it directly to KeyMatic without the help of a VCCU.
I've deployed the default eq3 AES Key and enabled AES support inside the sketch.
Pairing it to FHEM and then peering it to KeyMatic works fine, but the direct peering does not.
Once the pairing mode of an additional remote in KeyMatic is enabled, I start the pairing using the config button at my PCB (led blinks). Pressing any button of the recreated remote also does nothing.
I would be very thankful for any advice.

Thanks a lot!

#define SERIAL "ABCD"
#define DEVICE_ID {0x10, 0x08, 0x05}

#define USE_AES
#define HM_DEF_KEY 0xA4,0xE3... //default eq3 key
#define HM_DEF_KEY_INDEX 0

const struct DeviceInfo PROGMEM devinfo = {
  DEVICE_ID,     // Device ID
  SERIAL,           // Device Serial
  {0x00, 0xA6},           // HM-RC-Key4-2 
  0x11,                   // Firmware Version
  as::DeviceType::Remote, // Device Type
  {0x00, 0x00}            // Info Bytes
};
typedef AvrSPI<10, 11, 12, 13> SPIType;
typedef Radio<SPIType, 2> RadioType;
typedef AskSin<StatusLed<LED_PIN>, BatterySensorExt<A0, 0xFF>, RadioType> HalType;

class Hal : public HalType {
    AlarmClock btncounter;
  public:
    void init (const HMID& id) {
      HalType::init(id);
      battery.init(3, btncounter, 1);
      battery.low(25);
      battery.critical(22);
    }

    void sendPeer () {
      --btncounter;
    }

    bool runready () {
      return HalType::runready() || btncounter.runready();
    }

};

typedef RemoteChannel<Hal, 4, List0> ChannelType;
typedef MultiChannelDevice<Hal, ChannelType, 4, List0> RemoteType;

Hal hal;
RemoteType sdev(devinfo, 0x20);
ConfigButton<RemoteType> cfgBtn(sdev);

void setup()
{
  sdev.init(hal);
  buttonISR(cfgBtn, CONFIG_BUTTON_PIN);
  cfgBtn.init(CONFIG_BUTTON_PIN);
  sdev.initDone();
}

Sind direkte Verknüpfungen möglich?

Hallo,

ich habe den HB-UNI-Sen-RFID-RC von Jérôme nachgebaut (vielen Dank an Ihn für dieses geniale Projekt!).
AES im Scetch ist aktiviert, anlernen an die CCU2 ohne Fehler geklappt.
Die RFID Tags lassen sich registrieren und eine anmeldung von einem RFID Tag wird auch in der CCU WEB UI angezeigt.
Ein angelegtes Programm mit HB-UNI-Sen-RFID-RC und HM-Sec-Key funktioniert auch.
Eine direkte Verknüpfung lässt sich zwischen den beiden anlege, funktioniert aber nicht.
Der serielle Monitor am Arduino meldet auch keine Fehler.
Das alles mit eingestellten Übertragungsmodus "Standard" bei HB-UNI-Sen-RFID-RC.
Sobald ich den Übertragungsmodus beim HB-UNI-Sen-RFID-RC auf "Gesichert" ändere, Konfigurationsdaten für HB-UNI-Sen-RFID-RC stehen zur Übertragung an, und die Meldung erlischt nich weder beim annähern des RFID Tag noch durch drücken der Anlerntaste beim HB-UNI-Sen-RFID-RC.
Es gibt auch Fehlermeldungen im seriellen Monitor "CRC Failed" und "Signature FAILED".

Den AES Key habe ich im Scetch wie folgt angelegt:
Den System-Sicherheitsschlüssel aus CCU2 einfach StrToHex umgewandelt (als Beispiel 2Enten->32456E74656E) und im Format #define HM_DEF_KEY 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10 eingetragen.
Den Key Index habe ich aus \usr\local\config\keys genommen:

Current Index = 3
Key 1 = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Key 2 = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Key 3 = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Last Index = 2

und als #define HM_DEF_KEY_INDEX 6 eingetragen, da es in der Info steht, man solle den aktuellen Index mit 2 multiplizieren.
Key Verifikation mit crypttool -v -t 3 -k 'mein_Schlüssel' war OK.

Was mache ich falsch?

HM-LC-SWX-SM wrong channel count

When you define that it should be a HM-LC-SW2-SM or a HM-LC-SW1-SM it still sends 4 channels to the CCU when pairing.
I think this is because the channels are registered at object creation and not deregistered when the channel count is reduced.
Maybe it could be resolved with conditional compiling and different object creators.

Support for Sparkfun Pro Micro Board

Great Library!

I started to implement a Glass Breakage Detection Sensor from Abus by connecting it to an Sparkfun Pro Micro 3.3V Board (VID 1B4F, PID 9204).
When starting to use the AskSinPP library I got stuck with the missing support of this hardware (at least I suppose this is the root cause) in th AskSinPP library.
When compiling some example sketches from the AskSinPP library (e.g. HM-SEC-SD, which I plan to use) within Arduino IDE I get the attached error messages which point into this direction.
When I deliberately change the Board definition from "Sparkfun Pro Micro" to e.g. "Arduino Mini" the compile runs through without any error message.
I noticed that the same errors occur with the Board setting to "Arduino Micro" btw.

I'm rather new to Arduino programming, thus help would be appreciated here.

Best regards,

Rainer
error_log.txt

HM-SEC-SD Rauchmelder RESPONSE TIMEOUT

Hallo,

zunächst mal vielen Dank für dieses tolle Projekt! Ich habe bereits zwei HM-Lc-SW4 mit der AskSinpp Library gebaut, die hervorragend funktionieren.

Nun möchte ich meine billig-Funk-Rauchmelder auf Homematic umbauen und möchte daher den Rauchmelder Sketch HM-SEC-SD.ino verwenden. Zunächst mal Fragen zur Funktion:

Ich habe mir in dem Rauchmelder ein Signal gesucht, dass bei Alarm einen Hi-Pegel liefert und dieses auf den SENS1_PIN gelegt. Weiterhin habe ich an den SOUND_PIN einen Optokoppler angeschlossen, der den Test-Taster des Rauchmelders überbrückt (Hi-Pegel = Taster drücken). Kann man das so machen oder wie ist das eigentlich gedacht?

Das Peering mit FHEM hat problemlos geklappt. Der Rauchmelder war allerdings sofort auf Daueralarm, da der SOUND_PIN ständig Hi-Pegel hat. Ich konnte in FHEM sehen, wie smoke-Alarm im State hochgezählt wurden. Der SENS1_PIN Eingang scheint also zu funktionieren. Den SOUND_PIN habe ich erst mal wieder abgeklemmt, um den Daueralarm abzuschalten.

Ich habe dann ein set Rauchmelder alarmOff (und auch alarmOn, falls invertierte Logik) gesendet, doch der SOUND_PIN bleibt immer Hi. Und nun bekommt FHEM scheinbar keine Antwort mehr, ich kriege ständig nur noch Fehlermeldungen, siehe log:

2019-08-06_21:34:47 Rauchmelder MISSING ACK
2019-08-06_21:34:56 Rauchmelder unreachable
2019-08-06_21:47:55 Rauchmelder ResndFail
2019-08-06_21:47:55 Rauchmelder RESPONSE TIMEOUT:RegisterRead

RSSI liegt bei -59 und ein Test mit dem HM-Lc-SW4 Sketch zeigt, dass die Hardware bestens funktioniert.

Woran kann das liegen?

Achso, anfangs hatte ich kein Team gebildet, da ich erst später gelesen habe, dass man das scheinbar muss. Inzwischen habe ich aber ein set Rauchmelder peerChan 0 Rauchmelder single set actor gemacht und scheinbar hat der Rauchmelder das Team mit sich selbst gebildet. Also scheint ja schon noch Kommunikation stattzufinden.

Hier die Internals:

DEF 031234
 
HM_RPI_Modul_MSGCNT 9
HM_RPI_Modul_RAWMSG 0500003B0394410312340312340102C8
HM_RPI_Modul_RSSI -59
HM_RPI_Modul_TIME 2019-08-06 19:57:17
IODev HM_RPI_Modul
LASTInputDev HM_RPI_Modul
MSGCNT 9
NAME Rauchmelder
NOTIFYDEV global
NR 392
NTFY_ORDER 50-Rauchmelder
STATE unreachable
TESTNR 1
TYPE CUL_HM
lastMsg No:03 - t:41 s:031234 d:031234 0102C8
peerList self01
protCmdDel 15
protLastRcv 2019-08-06 19:57:16
protRcv 3 last_at:2019-08-06 19:57:16
protRcvB 3 last_at:2019-08-06 19:57:16
protResnd 11 last_at:2019-08-06 22:05:04
protResndFail 11 last_at:2019-08-06 22:05:08
protSnd 20 last_at:2019-08-06 22:04:57
protSndB 31 last_at:2019-08-06 22:05:04
protState CMDs_done_Errors:1
rssi_at_HM_RPI_Modul cnt:9 min:-64 max:-57 avg:-61.11 lst:-59
sdTeam sdLead

Vielen Dank!

AskSinPP-3 oder AskSInPP-4 als ZIP Bibliothek hinzufügen

Hallo,

Das Hinzufügen der ZIP Bibliotheken AskSinPP-3 und AskSinPP-4 schlägt fehl: "Angegebener Ordner/ZIP-Datei enthält keine gültige Bibliothek"

Ich nutze die Arduino-IDE Version 1.8.12.

Das Hinzufügen der Bibliotheken AskSinPP-1, AskSinPP-2 sowie AskSin-Master funktioniert.

Kann mir jemand bitte ein Tipp geben woran das liegt oder was ich falsch mache ?

Gruss vom Niederrhein
Juergen

Switch: Info Message auch an MasterID

IST-Zustand:
Wird ein Switch mittels internem self-peer Taster geschaltet, wird diese Info nur an sich selbst (Empfänger = Sender) geschickt.

-> 0B 02 22 40 123456 123456 01 02
<- 0E 02 80 02 123456 123456 01 01 C8 00 57

SOLL-Zustand:
Wird ein Switch mittels internem self-peer Taster geschaltet, so muss der Schaltzustand BIDI zur Zentrale übertragen werden.
Ist das Device mit keiner Zentrale gepairt, wird der Schaltzustand BCAST an 000000 gesendet.

Schalten eines originalen HM Zwischensteckers:

AUS:
ignore 0D 4C A4 10 4B2FEB 2BE14D 06 01 00 00
ignore 0A 4C 80 02 2BE14D 4B2FEB 00

EIN:
ignore 0D 4F A4 10 4B2FEB 2BE14D 06 01 C8 00
ignore 0A 4F 80 02 2BE14D 4B2FEB 00

Is everything available to builde a thermostat?

I've got now many STM32F103 boards and what to build a thermostat such as the Homematic HM-TC-IT-WM-W-EU which has temperatur and humidity and can send back control commands. I have copied at the the channels and parameters from the homatic user guide which describes all the parameter.
I have used the stm32 example HM-LC-SWX-SM and at least the pairing with Homegear works.
I'm wondering if I have everything as bases clases which are required tuild a Thermostat like the HM-TC-IT-WM-W-EU? And are there somewhere the device models (not types) defined or can I use any numbers (in the weather sensor sample {0x00,0x3d}, is used, in the switch model has a name HM_LC_SW4_SM is used).

This are the channel "definitions" from homematic for the thermostat HM-TC-IT-WM-W-EU. Has anybody build such a similar device?

/* HM-TC-IT-WM-W-EU
channeltype channelnnr
WEATHER_TRANSMIT 1
THERMALCONTROL_TRANSMIT 2
WINDOW_SWITCH_RECEIVER 3
REMOTECONTROL_RECEIVER 6
SWITCH_TRANSMIT 7

WEATHER_TRANSMIT 1
TEMPERATURE float lesend über Ereignisse -10, +50
HUMIDITY integer lesend über Ereignisse 0 99

THERMALCONTROL_TRANSMIT 2
CONTROL_MODE option lesend über Ereignisse
LOWBAT_REPORTING boolean lesend über Ereignisse
COMMUNICATION_REPORTING boolean lesend über Ereignisse
WINDOW_OPEN_REPORTING boolean lesend über Ereignisse
BATTERY_STATE float lesend über Ereignisse
BOOST_STATE integer
ACTUAL_TEMPERATURE float
ACTUAL_HUMIDITY float
SET_TEMPERATURE
AUTO_MODE
MANU_MODE
BOOST_MODE
COMFORT_MODE
LOWERING_MODE
PARTY_MODE_SUBMIT
PARTY_TEMPERATURE
PARTY_TEMPERATURE
PARTY_START_TIME
PARTY_START_DAY
PARTY_START_MONTH
PARTY_START_YEAR
PARTY_STOP_TIME
PARTY_STOP_DAY
PARTY_STOP_MONTH
PARTY_STOP_YEAR

WINDOW_SWITCH_RECEIVER 3
REMOTECONTROL_RECEIVER 6

SWITCH_TRANSMIT 7
DECISION_VALUE integer lesend über Ereignisse 0..255

Füllstandssensor mit lokaler Displayanzeige

Hallo,
ich wende mich heute an euch, weil ich mit o.g. Projekt einfach nicht weiter komme:
Ich beabsichtige, eine Füllstandsmessung mittels Ultraschallsensor HC-SR04 zu realisieren, bei gleichzeitiger Temperaturmessung, um die Temperaturabhängigkeit der Schallgeschwindigkeit zu kompensieren, und den Füllstand und die Temperatur lokal auf einem OLED-Display 128x64 anzuzeigen. Dazu verwende ich einen Arduino Pro mini.
Das funktioniert auch hervorragend, wenn ich den folgenden Beispiel-Skech verwende:

`[code]
/*
Fuellstandssensor V.1.0
Autor: H. Melzer
Grundlage: Ardudronix
https://www.ardutronix.de
*/

// Variable deklarieren
int verzoegerung = 5000;
double entfernung = 0.0;
double heightTank=110.0, fuellhoehe;

//Definitionen fuer HC-SR04
#define TRIG_PIN 7
#define ECHO_PIN 6

//Display-Bibliotheken einbinden
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>

//Bibliothek für den Temperaturfüler
#include <DallasTemperature.h>

//DS18B20 Sensors verbunden mit Pin 3
OneWire oneWire(3);

//Ultrasonic-Sensor einbinden
#include "src\HCSR04.h"

// Auflösung des Displays setzen
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define Dallas

//Initialisierung des Sensor zur Benutzung der Digital-Pins 7 und 6
//UltraSonicDistanceSensor distanceSensor(trigger, echo);
UltraSonicDistanceSensor distanceSensor(TRIG_PIN, ECHO_PIN);
DallasTemperature sens_temp(&oneWire);

void setup()
{
//Einrichten der Kommunikation mit der Arduino IDE
Serial.begin (115200);
Serial.println("Temperatursensor - DS18B20");

//Starten der Kommunikation mit dem Sensor
sens_temp.begin();

//Display mit I2C-Adresse 0x3c initialisieren
if(!display.begin(/SSD1306_EXTERNALVCC/SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x64
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}

display.clearDisplay(); //Verhindert die Anzeige des Adafruit-Logos
display.display();//Bereitet nächste Anzeige vor
display.setTextColor(WHITE); //Textfarbe setzen (hier tatsächlich aber nicht weiß
display.setFont(); //Standard-Text-Font verwenden
}

void loop()
{
sens_temp.requestTemperatures(); //Temperatur abfragen
float temperature = sens_temp.getTempCByIndex(0); //Temperatur des Gerätes mit Index 0 in Variable schreiben
//Ausgabe an Serial Monitor in °C und °F
Serial.println("Temperature: ");
Serial.print(sens_temp.getTempCByIndex(0));Serial.println("°C");
Serial.print(sens_temp.getTempFByIndex(0));Serial.println("°F");
Serial.println();

double entfernung = distanceSensor.measureDistanceCm(temperature);

// Füllhöhe berechnen
fuellhoehe = heightTank - entfernung;

//Ausgabe an Serial Monitor
Serial.println(entfernung);
Serial.println(fuellhoehe);
Serial.println("");

if (fuellhoehe >= heightTank-10 || fuellhoehe < 0)
{
display.clearDisplay();
display.setTextSize(2);
display.setCursor(18, 0);
display.println("Achtung!");
display.setCursor(16, 20);
display.println("Messwert");
display.setCursor(4, 40);
display.println("fehlerhaft");
display.display();
}
else
{
display.clearDisplay();
display.invertDisplay(false);
display.setCursor(18, 0);
display.setTextSize(2);
display.println("F\x81\llh\x94\he");
display.setCursor(20, 20);
display.setTextSize(2);
display.print(fuellhoehe);
display.println(" cm");
display.drawLine (10, 38, display.width ()-10, 38 , WHITE);
display.setCursor(20, 46);
display.print(temperature);
display.print(" \xf7\C");
display.display();
}
delay(verzoegerung);
}
[/code]
`
Hier der Versuchsaufbau mit der Anzeige:
Versuchsaufbau

In der Folge habe ich nun das Ergebnis auf eine Implementierung für Homematic mit AskSinPP anzuwenden versucht. Schwierig hierbei war erst einmal, den Programmumfang so zu gestalten, dass der Speicher ausreichte, was nur mit einigen Tricks und unter Verwendung der Master-Version oder Version 3 der AskSinPP gelang. Ein Problem konnte ich jedoch nicht beseitigen:
Eine Initialisierung des Displays mit der erforderlichen I2C-Adresse 0x3C gelang nur, wenn ich die Anzeigegröße verringert habe. Interessanterweise funktioniert es wieder bei 128 x 56, Allerdings wird in jedem Fall nicht jedes Pixel angesprochen, das Display lässt praktisch jede zweite Zeile aus.
Hier die Anzeige im Vergleich, wobei auch das Setzen der Textgröße nichts bringt:
AnzeigeAnzeige

Auch die DEPRECATED-Version für das Adafruit-Display (Zeile 46+47 des Sketches) liefert die gleichen Ergebnisse).
Hat AsksinPP ein Problem mit I2C oder der Adresse 0x3C oder liegt es an der geänderte Bibliothek für den Temperatursensor?
Nachfolgend mein Code, wie erzwar funktioniert, aber eben nicht zufriedenstellend:

`
[code]
//---------------------------------------------------------
// Fuellstandssensor V.1.0
// HB-Sonic-Lev1
// (C) 2020 H. Melzer (Creative Commons)
// https://creativecommons.org/licenses/by-nc-sa/4.0/
// You are free to Share & Adapt under the following terms:
// Give Credit, NonCommercial, ShareAlike// +++
// AskSin++ 2016-10-31 papa Creative Commons
// Basics: Ardudronix
// https://www.ardutronix.de,
// arduino-lib-hc-sr04 from Martin Sosic
// https://github.com/Martinsos/arduino-lib-hc-sr04
// Sens_DS18X20
// 2018-08-12 Tom Major (Creative Commons)
//---------------------------------------------------------

//---------------------------------------------------------
// !! NDEBUG sollte aktiviert werden, wenn die Sensorentwicklung und die Tests abgeschlossen sind und das Gerät in den 'Produktionsmodus' geht.
// Damit wird Flash- und RAM-Speicher eingespart.
// Insbesondere die RAM-Einsparungen sind wichtig für die Stabilität / dynamische Speicherzuweisungen etc.
// Dies beseitigt dann auch die mögliche Arduino-Warnung 'Low memory available, stability problems may occur'.
//
#define NDEBUG

//---------------------------------------------------------

#define EI_NOTEXTERNAL
#include <EnableInterrupt.h>
#include <AskSinPP.h>
#include <LowPower.h>
#include <MultiChannelDevice.h>
#include <Register.h>
#include <HCSR04.h>
#include "Sens_DS18X20.h" // HB-UNI-Sensor1 custom sensor class

// Bibliotheken zur Kommunikation
#include <SPI.h>
#include <Wire.h>
#include <OneWire.h>

#ifdef NDEBUG
//Display-Bibliotheken einbinden
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// Adafruit_SSD1306.h Zeile 29: #define SSD1306_128_32 ///< DEPRECATED: old way to specify 128x32 screen
//Adafruit_SSD1306 display(4);

// Definitionen für das Display
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
//Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#endif;

// Pin Definitionen Allgemein
#define CONFIG_BUTTON_PIN 8
#define LED_PIN 4

// Pin und Address Definitionen Temperatur-Sensor
#define ONEWIRE_PIN 3

//Definitionen fuer HC-SR04
#define TRIG_PIN 7
#define ECHO_PIN 6

// Sonstige Definitionen
#define CLOCK_SYSCLOCK
#define CLOCK sysclock
#define SAVEPWR_MODE Sleep<>

UltraSonicDistanceSensor distanceSensor(TRIG_PIN, ECHO_PIN); // Initialize sensor.

// number of available peers per channel
#define PEERS_PER_CHANNEL 6

//---------------------------------------------------------
// all library classes are placed in the namespace 'as'
using namespace as;

// Hier Definition aller Geräteeigenschaften
// Bei mehreren Geräten des gleichen Typs (Fuellstandssensor) muss Device ID und Device Serial unterschiedlich sein!
// Device ID und Device Serial müssen an dieser Stelle geändert werden, damit die Geräte ordentlich angemeldet werden können.

#define cDEVICE_ID { 0xF7, 0xA5, 0x03 }
#define cDEVICE_SERIAL "HMSonicLe1"

const struct DeviceInfo PROGMEM devinfo = {
cDEVICE_ID, // Device ID
cDEVICE_SERIAL, // Device Serial
{ 0xF7, 0x01 }, // Device Model
0x10, // Firmware-Version
0x53, // Device Type
{ 0x01, 0x01 } // Info Bytes
};

// Konfigure der verwendeten Hardware
typedef AvrSPI<10, 11, 12, 13> SPIType;
typedef Radio<SPIType, 2> RadioType;
typedef StatusLed<LED_PIN> LedType;
typedef AskSin<LedType, NoBattery, RadioType> BaseHal;

class Hal : public BaseHal {
public:
void init(const HMID& id)
{
BaseHal::init(id);
}

bool runready() {
  return CLOCK.runready() || BaseHal::runready();
}

} hal;

class MeasureEventMsg : public Message {
public:
void init(uint8_t msgcnt, int16_t temp, uint16_t Level_mm, uint8_t percent)
{
uint8_t t1 = (temp >> 8) & 0x7f;
uint8_t t2 = temp & 0xff;

  // als Standard wird BCAST gesendet um Energie zu sparen, siehe Beschreibung unten.
  // Bei jeder 5. Nachricht senden wir stattdessen BIDI|WKMEUP, um eventuell anstehende Konfigurationsänderungen auch
  // ohne Betätigung des Anlerntaster übernehmen zu können (mit Verzögerung, worst-case 5x Sendeintervall).
  uint8_t flags = BCAST;
  if ((msgcnt % 5) == 1) {
    flags = BIDI | WKMEUP;
  }
  Message::init(14, msgcnt, 0x53, flags, t1, t2);
  // Message Length (first byte + param.): 11 + payload
  //  1 Byte payload -> length 12
  //  3 Byte payload -> length 14
  // max. payload: 17 Bytes (https://www.youtube.com/watch?v=uAyzimU60jw)

  // BIDI|WKMEUP: erwartet ACK vom Empfänger, ohne ACK wird das Senden wiederholt
  // LazyConfig funktioniert, d.h. eine anstehende Conf.Änderung von der CCU wird nach dem nächsten Senden übernommen. Aber erhöhter
  // Funkverkehr wegen ACK
  //
  // BCAST: ohne ACK zu Erwarten, Standard für HM Sensoren.
  // LazyConfig funktioniert nicht, d.h. eine anstehende Conf.Änderung von der CCU muss durch den Config Button am Sensor übernommen
  // werden!!

  // papa:
  // BIDI - fordert den Empfänger auf ein Ack zu schicken. Das wird auch zwingend für AES-Handling gebraucht. BCAST - signalisiert
  // eine Broadcast-Message. Das wird z.B. verwendet, wenn mehrere Peers vor einen Sensor existieren. Es wird dann an einen Peer
  // gesndet und zusätzlich das BCAST-Flag gesetzt. So dass sich alle die Nachrricht ansehen. Ein Ack macht dann natürlich keinen Sinn
  // - es ist ja nicht klar, wer das senden soll.
  //
  // WKMEUP - wird für LazyConfig verwendet. Ist es in einer Message gesetzt, so weiss
  // die Zentrale, dass das Geräte noch kurz auf weitere Nachrichten wartet. Die Lib setzt diese Flag für die StatusInfo-Message
  // automatisch. Außerdem bleibt nach einer Kommunikation der Empfang grundsätzlich für 500ms angeschalten.

  // Level
  pload[0] = (Level_mm >> 8) & 0xff;
  pload[1] = Level_mm & 0xff;

  // percent
  pload[2] = percent;
}

};

// die "freien" Register 0x20/21 werden hier als 16bit memory für das Update-Intervall in Sek.,
// die Register 0x22/0x23 für den konf. Parameter Bef_Hoehe_Sens und
// die Register 0x34/0x35 für den konf. Parameter Max_Fuell_Hoehe benutzt

DEFREGISTER(Reg0, MASTERID_REGS, DREG_TRANSMITTRYMAX, 0x20, 0x21, 0x22, 0x23, 0x34, 0x35)
class SensorList0 : public RegList0 {
public:
SensorList0(uint16_t addr)
: RegList0(addr)
{
}
bool updIntervall(uint16_t value) const {
return this->writeRegister(0x20, (value >> 8) & 0xff) && this->writeRegister(0x21, value & 0xff);
}
uint16_t updIntervall() const {
return (this->readRegister(0x20, 0) << 8) + this->readRegister(0x21, 0);
}
bool Bef_Hoehe_Sens(uint16_t value) const {
return this->writeRegister(0x22, (value >> 8) & 0xff) && this->writeRegister(0x23, value & 0xff);
}
uint16_t Bef_Hoehe_Sens() const {
return (this->readRegister(0x22, 0) << 8) + this->readRegister(0x23, 0);
}
bool Max_Fuell_Hoehe(uint16_t value) const {
return this->writeRegister(0x34, (value >> 8) & 0xff) && this->writeRegister(0x35, value & 0xff);
}
uint16_t Max_Fuell_Hoehe() const {
return (this->readRegister(0x34, 0) << 8) + this->readRegister(0x35, 0);
}
void defaults()
{
clear();
transmitDevTryMax(6);
updIntervall(30);
Bef_Hoehe_Sens(2000);
Max_Fuell_Hoehe(1800);
}
};

class MeasureChannel : public Channel<Hal, List1, EmptyList, List4, PEERS_PER_CHANNEL, SensorList0>, public Alarm {

MeasureEventMsg msg;

int16_t  temperature10;
uint8_t  percent;
uint16_t Level_mm;

Sens_DS18X20 ds18x20;

public:
MeasureChannel()
: Channel()
, Alarm(seconds2ticks(60))
, temperature10(0)
, Level_mm(0)
, percent(0)
{
}
virtual ~MeasureChannel() {}

virtual void trigger(AlarmClock& clock)
{
  measure();

  uint8_t msgcnt = device().nextcount();
  msg.init(msgcnt, temperature10, Level_mm, percent);
  device().sendPeerEvent(msg, *this);

  // reactivate for next measure
  uint16_t updCycle = this->device().getList0().updIntervall();
  set(seconds2ticks(updCycle));
  clock.add(*this);
}

void measure()
{
  ds18x20.measure();
  uint16_t Bef_Hoehe_Sens = this->device().getList0().Bef_Hoehe_Sens();
  uint16_t Max_Fuell_Hoehe = this->device().getList0().Max_Fuell_Hoehe();
  temperature10 = ds18x20.temperature();
  uint16_t entfernung_mm = 10 * distanceSensor.measureDistanceCm(temperature10 / 10);
  DPRINT(F("Entfernung: ")); DPRINT(entfernung_mm); DPRINTLN(F(" mm"));
  Level_mm = Bef_Hoehe_Sens - entfernung_mm;
  percent = 100.0 * Level_mm / Max_Fuell_Hoehe;
  DPRINT(F("Füllgrad: "));   DDEC(percent);         DPRINTLN(F(" %"));
  DPRINT(F("Level: "));      DPRINT(Level_mm);      DPRINTLN(F(" mm"));

#ifdef NDEBUG
display.clearDisplay();
display.invertDisplay(false);
display.setTextSize(1);
display.setCursor(18, 0);
display.println("F\x81\llh\x94\he");
display.setCursor(20, 10);
display.print(Level_mm / 10);
display.println(" cm");
display.drawLine (10, 19, display.width () - 10, 19 , WHITE);
display.setCursor(20, 23);
display.print(temperature10/10);
display.print(" \xf7\C");
display.display();
#endif
}

void initSensors()
{
  ds18x20.init(ONEWIRE_PIN);
  DPRINTLN(F("Sensor setup done"));
  DPRINT(F("Serial: "));
  DPRINTLN(cDEVICE_SERIAL);
  DPRINTLN(F("Clock SYSCLOCK"));
}

void setup(Device<Hal, SensorList0>* dev, uint8_t number, uint16_t addr)
{
  Channel::setup(dev, number, addr);
  initSensors();
  set(seconds2ticks(5));    // first message in 5 sec.
  CLOCK.add(*this);
}

void configChanged()
{
  // DPRINTLN(F("Config changed: List1"));
}

uint8_t status() const {
  return 0;
}

uint8_t flags() const {
  return 0;
}

};

class SensChannelDevice : public MultiChannelDevice<Hal, MeasureChannel, 1, SensorList0> {
public:
typedef MultiChannelDevice<Hal, MeasureChannel, 1, SensorList0> TSDevice;
SensChannelDevice(const DeviceInfo& info, uint16_t addr)
: TSDevice(info, addr)
{
}
virtual ~SensChannelDevice() {}

virtual void configChanged()
{
  TSDevice::configChanged();
  DPRINTLN(F("Config Changed: List0"));

  uint8_t ledMode = this->getList0().ledMode();
  DPRINT(F("ledMode: "));
  DDECLN(ledMode);

  uint8_t txDevTryMax = this->getList0().transmitDevTryMax();
  DPRINT(F("transmitDevTryMax: "));
  DDECLN(txDevTryMax);

  uint16_t updCycle = this->getList0().updIntervall();
  DPRINT(F("updCycle: "));
  DDECLN(updCycle);

  uint16_t hTank = this->getList0().Bef_Hoehe_Sens();
  DPRINT(F("Bef_Hoehe_Sens: "));
  DDECLN(hTank);

  uint16_t Max_Fuell_Hoehe = this->getList0().Max_Fuell_Hoehe();
  DPRINT(F("Max_Fuell_Hoehe: "));
  DDECLN(Max_Fuell_Hoehe);
}

};

SensChannelDevice sdev(devinfo, 0x20);
ConfigButton cfgBtn(sdev);

void setup()
{
#ifdef NDEBUG
Serial.begin(115200);
#endif;
DINIT(115600, ASKSIN_PLUS_PLUS_IDENTIFIER);
sdev.init(hal);
buttonISR(cfgBtn, CONFIG_BUTTON_PIN);
sdev.initDone();

#ifdef NDEBUG
//Display mit I2C-Adresse 0x3c initialisieren
//display.begin(SSD1306_SWITCHCAPVCC, 0x3c);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3c)) { // Address 0x3C for 128x64
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
display.clearDisplay(); //Verhindert die Anzeige des Adafruit-Logos
display.display();//Bereitet nächste Anzeige vor
display.setTextSize(1); //Textgröße setzen
display.setTextColor(WHITE); //Textfarbe setzen (hier tatsächlich aber nicht weiß
display.setFont(); //Standard-Text-Font verwenden
display.setCursor(5, 10); //Begin der Textausgabe setzen

#endif;

}

void loop()
{
bool worked = hal.runready();
bool poll = sdev.pollRadio();
if (worked == false && poll == false) {
// deep discharge protection
// if we drop below critical battery level - switch off all and sleep forever
// if nothing to do - go sleep
hal.activity.savePower<SAVEPWR_MODE>(hal);
}
}
[/code]
`

Ich hoffe auf Hilfe, vielen Dank.

implement RFM69 support?

Hi,

very great work here, Thank you so much for your effort. I'm extremely excited to jump into this and start developing my own Homematic devices. In this process I hope to learn more about this library, the AskSin protocol and so forth to hopefully eventually be able to contribute something to your great work.

One thing however, made me curious. Would it be possible for you to start working on RFM69 support at some point? Those RFM69 modules are much easier to source (e.g. from official distributors like Pollin or Mouser) and seem to have much better range and TX power.

I think, because of this, it would be a logical step to make this library work with the RFM69 modules, to be future-proof.

There has already been some effort here:
https://forum.fhem.de/index.php?topic=49300.0
https://forum.fhem.de/index.php?topic=57486.660
https://forum.fhem.de/index.php?topic=48433.0

but unfortunately at the moment I really barely understand what's going on in those threads - firstly because I'm not that experienced in RF technology (no idea what DataWhitening or preambles are, e.g.) and secondly because the whole Homematic protocol is totally new for me and I have absolutely no idea what is going on on low level tx/rx layer.

So, once again, what is your opinion on implementing RFM69 support?

Cannot assign HM Key

Hey there,
I am trying to recreate a HM-RC-KEY4-3. Unfortunately, when issuing the assignHmKey command with my CUL, my module responds with NACK. How do I activate the storage of

  DEVICE_ID,     // Device ID
  SERIAL,           // Device Serial
  {0x00, 0xD6},           // Device Model
  0x11,                   // Firmware Version
  as::DeviceType::Remote, // Device Type
  {0x00, 0x00}            // Info Bytes
};
typedef AvrSPI<10, 11, 12, 13> SPIType;
typedef Radio<SPIType, 2> RadioType;
typedef AskSin<StatusLed<7>, BatterySensorExt<A0, 0xFF, 1>, RadioType> HalType;

class Hal : public HalType {
    AlarmClock btncounter;
  public:
    void init (const HMID& id) {
      HalType::init(id);
      battery.init(3, btncounter);
      battery.low(36);
      battery.critical(34);
    }

    void sendPeer () {
      --btncounter;
    }

    bool runready () {
      return HalType::runready() || btncounter.runready();
    }

};

typedef RemoteChannel<Hal, PEERS_PER_CHANNEL, List0> ChannelType;
typedef MultiChannelDevice<Hal, ChannelType, 4> RemoteType;

Hal hal;
RemoteType sdev(devinfo, 0x20);
ConfigButton<RemoteType> cfgBtn(sdev);

Thanks for your help.

Integration in FHEM Update ??

Hi,

would it a good Idea to integrate it in automated FHEM updating ?

Example:
update add https://raw.githubusercontent.com/pa-pa/AskSinPP/master/examples/custom/contrib/FHEM/controls_asksinpp_fhem.txt

controls_asksinpp_fhem.txt :

If its no good idea, please close this ticket.

Regards

PS: Example for controls_asksinpp_fhem.txt
DEL ./FHEM/ABFALL_getEvents.pm
UPD 2018-06-13_12:34:34 23027 FHEM/ABFALL_getEvents.pm
DEL ./FHEM/ABFALL_setUpdate.pm
UPD 2018-06-13_12:34:34 30289 FHEM/ABFALL_setUpdate.pm
DEL ./FHEM/57_ABFALL.pm
UPD 2018-06-13_12:34:34 9873 FHEM/57_ABFALL.pm

HM-RC-8 not working properly

Hello pa-pa, I flashed my arduino pro mini (with CC1101 module) with your V3 HM-RC-8. Everything looks fine. The Device could be connected to my Raspberrymatic. I changed every channel transmission from secured to default. For testing I didn't connect all of the buttons, just button 1 (Pin 14) and button 2 (Pin 3) to Ground).

I enabled logging but the log shows nothing, desn't matters how often I pressed the buttons.

When I flash the HM-RC-P1 Firmware from Jerome (JP112SDL) then the Button 1 works fine.

Can you help me?

Thanks and best regards
Thorsten

grafik

Kanalparameter ohne Wirkung ?

Ich hab mir eine Schaltung für den Bewegungsmelder zusammengebaut und den entsprechenden Sketch draufgespielt. Funktioniert auch als Bewegungsmelder prima, nur leider sehr empfindlich.
Ich habe dann versucht bei den Kanalparametern Anzahl Impulse pro Zeit hochzustehen. Allerdings habe ich den Eindruck, dass das Einstellen von Kanalparametern keine Wirkung hat. Werden diese unterstützt ?

bright status in motion.h

I was wondering about far to high brightness values after starting the motion sensor sketch/device.
The root cause for it sits in motion.h

  uint8_t status () {
    brightsens.measure();
    uint32_t bright = brightsens.brightness();
    if( bright > maxbright ) {
      maxbright = bright;
    }
    // scale to value between 0 - 255s
    return (uint8_t)(bright * 255UL / maxbright);
  }

The first bright measurement value sets the maxbright value, so that the return value will be 255 and it takes a whole day cycle to get the highest bright value for setting the maxvalue to a resonable size.

A better solution could be - assuming the followin:
BH1750 measures the brightness in lux _brightness is a uint16_t
TSL2561 measures the brightness in lux _brightness is a uint16_t
MAX44009 measures the brightness in lux _brightness is a uint16_t

So we get in any case a 16bit integer, reflecting a lux value.
Motion.h transmits an 8bit brightness value, so the challange is to scale down.
In the code above it is linear and if the sensor is in an bright environment the sensitivity is reduced.

If we would replace the code with:

  uint8_t status () {
    brightsens.measure();
    uint32_t bright = brightsens.brightness();
    if( bright > 0xffff ) bright = 0xffff;
    return sqrt(bright); 
  }

sqrt will scale down the brightness with an exponent of 2, which looks like
Bild1

What do you think?

pwmtable starts at 1?

I've drafted the Dim1PWM

dim1-fritzing

And uploaded HM-LC-Dim1PWM-CV.ino

  • LED Strip is off on power on
  • Dimming between 10-100% works as expected
    BUT when I dimm to 0% the LEDs are still glowing cause the GPIO still emits.

When I alter the pwmtable to start from 0 it works as expected.

Is this a Bug or am I doing smth wrong?

Dimmer mit 2 Buttons "komisches verhalten"

Die internen Gerätetasten verhalten sich etwas merkwürdig.

Nach dem Anlernen sind beide Tasten auf Experte eingestellt. Kann man hier Dimmer aus / dunkler bzw Dimmer ein / heller als Standard hinterlegen?

Verhalten
Drücke ich kurz auf Btn1 geht die LED an.
Drücke ich kurz auf Btn2 geht die LED aus.
Drücke ich lang auf Btn1 dimmt die LED hoch.
Drücke ich lang auf Btn2 dimmt die LED runter.

Änder ich in der CCU die Config der Buttons zB auf
Btn1: Dimmer an; Pegel 50%
Btn2: Dimmer aus

Dann muss ich den Btn1 zweimal drücken damit die LED auf 50% geht.
Auch Btn2 schaltet die LED erst nach dem zweiten press aus.
Ich sehe jeweils beide "pressed" im Monitor.

Ändere ich nun den Dimmwert per CCU, dann schaltet Btn2 die LED nicht aus.
Bei einem LONGPRESS dimmt die LED runter. Jetzt geht ein SHORT wieder zum Ausschalten.

Expand Sketch Code

//- -----------------------------------------------------------------------------------------------------------------------
// AskSin++
// 2016-10-31 papa Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
//- -----------------------------------------------------------------------------------------------------------------------

// define this to read the device id, serial and device type from bootloader section
// #define USE_OTA_BOOTLOADER

#define EI_NOTEXTERNAL
#include <EnableInterrupt.h>
#include <AskSinPP.h>
#include <LowPower.h>

#include <Dimmer.h>


// we use a Pro Mini
// Arduino pin for the LED
// D4 == PIN 4 on Pro Mini
#define LED_PIN 4
// Arduino pin for the config button
// B0 == PIN 8 on Pro Mini
#define CONFIG_BUTTON_PIN 8

#define DIMMER_PIN 3
#define BUTTON1_PIN 7
#define BUTTON2_PIN 9

// number of available peers per channel
#define PEERS_PER_CHANNEL 4

// all library classes are placed in the namespace 'as'
using namespace as;

// define all device properties
const struct DeviceInfo PROGMEM devinfo = {
    {0x11,0x12,0x22},       // Device ID
    "papa111222",           // Device Serial
    {0x00,0x67},            // Device Model
    0x25,                   // Firmware Version
    as::DeviceType::Dimmer, // Device Type
    {0x01,0x00}             // Info Bytes
};

/**
 * Configure the used hardware
 */
typedef AvrSPI<10,11,12,13> SPIType;
typedef Radio<SPIType,2> RadioType;
typedef StatusLed<LED_PIN> LedType;
typedef AskSin<LedType,NoBattery,RadioType> HalType;
typedef DimmerChannel<HalType,PEERS_PER_CHANNEL> ChannelType;
typedef DimmerDevice<HalType,ChannelType,3,3,PWM8<> > DimmerType;

HalType hal;
DimmerType sdev(devinfo,0x20);
ConfigButton<DimmerType> cfgBtn(sdev);
InternalButton<DimmerType> btn1(sdev, 4);
InternalButton<DimmerType> btn2(sdev, 5);

void setup () {
  DINIT(57600,ASKSIN_PLUS_PLUS_IDENTIFIER);
  if( sdev.init(hal,DIMMER_PIN) ) {
    sdev.channel(1).peer(btn1.peer(), btn2.peer());
  }
  buttonISR(cfgBtn, CONFIG_BUTTON_PIN);
  buttonISR(btn1, BUTTON1_PIN);
  buttonISR(btn2, BUTTON2_PIN);
  sdev.initDone();
}

void loop() {
  hal.runready();
  sdev.pollRadio();
}

AskSinPP/examples/stm32/HM-LC-DW-WM/HM-LC-DW-WM.ino

Hallo,

beim compilieren unter PlatformIO tritt folgender Fehler auf:
Die Datei "Quelle" kann nicht geöffnet werden: "OneWireSTM.h".

Unter PlatformIO finde ich diese Library nicht. Unter rogerclarkmelbourne Arduino_STM32 finde ich diese Library
aber binde ich diese Library ein bekomme ich sehr viele Fehler angezeigt.

Wie löse ich das Problem?

Dimmer for dualwhite

Hello, could you perhaps integrate the actuator HM-LC-DW-WM?
greetings
Harald

HM-ES-TX-WM inputs

Why does the HM-ES-TX-WM have 2 inputs?
Only pulses from input A1 seem to be counted in the CCU while pulses on input A0 are not being counted.
Allthough the counter values of both inputs are being transmitted to the CCU (monitored via IOBroker) only the value that is transmitted in second position is recogniced in the CCU.

HB-UNI-SEN-WEA Bug FHEM?

kurze Fehlermeldung von meiner Seite zum HB-UNI-SEN-WEA in FHEM:

  1. Scheinbar klappt da was mit den peers nicht, denn ich erhalte bei getConfig
2019.11.09 16:37:05 1: PERL WARNING: Use of uninitialized value $peerRq in string eq at ./FHEM/10_CUL_HM.pm line 8210.
2019.11.09 16:37:05 1: stacktrace:
2019.11.09 16:37:05 1:     main::__ANON__                      called by ./FHEM/10_CUL_HM.pm (8210)
2019.11.09 16:37:05 1:     main::CUL_HM_getRegFromStore        called by ./FHEM/10_CUL_HM.pm (8424)
2019.11.09 16:37:05 1:     main::CUL_HM_updtRegDisp            called by ./FHEM/10_CUL_HM.pm (3447)
2019.11.09 16:37:05 1:     main::CUL_HM_parseCommon            called by ./FHEM/10_CUL_HM.pm (1536)
2019.11.09 16:37:05 1:     main::CUL_HM_Parse                  called by fhem.pl (3946)
2019.11.09 16:37:05 1:     main::Dispatch                      called by ./FHEM/00_CUL.pm (948)
2019.11.09 16:37:05 1:     main::CUL_Parse                     called by ./FHEM/00_CUL.pm (832)
2019.11.09 16:37:05 1:     main::CUL_Read                      called by fhem.pl (3750)
2019.11.09 16:37:05 1:     main::CallFn                        called by fhem.pl (750)

Sowie regelmäßig den Logeintrag

2019.11.09 16:53:29 1: PERL WARNING: Use of uninitialized value in string eq at ./FHEM/10_CUL_HM.pm line 8689.
2019.11.09 16:53:29 1: stacktrace:
2019.11.09 16:53:29 1:     main::__ANON__                      called by ./FHEM/10_CUL_HM.pm (8689)
2019.11.09 16:53:29 1:     main::CUL_HM_getRegInfo             called by ./FHEM/10_CUL_HM.pm (3956)
2019.11.09 16:53:29 1:     main::CUL_HM_Get                    called by fhem.pl (3750)
2019.11.09 16:53:29 1:     main::CallFn                        called by fhem.pl (1957)
2019.11.09 16:53:29 1:     main::CommandGet                    called by fhem.pl (1238)
2019.11.09 16:53:29 1:     main::AnalyzeCommand                called by ./FHEM/01_FHEMWEB.pm (2683)
2019.11.09 16:53:29 1:     main::FW_fC                         called by ./FHEM/01_FHEMWEB.pm (911)
2019.11.09 16:53:29 1:     main::FW_answerCall                 called by ./FHEM/01_FHEMWEB.pm (580)
2019.11.09 16:53:29 1:     main::FW_Read                       called by fhem.pl (3750)
2019.11.09 16:53:29 1:     main::CallFn                        called by fhem.pl (750)

sobald der Sensor in Betrieb ist. Weiterhin ist der Druck um Faktor 10 in "state" zu hoch, was sich hier beheben lässt: https://github.com/pa-pa/AskSinPP/blob/19ecad710efaeb914eadd90a8a2fbdc0e489e226/examples/custom/contrib/FHEM/HMConfig_AskSinPPCustom.pm#L387

Vielen Dank für Eure Arbeit- hier ist echt etwas ganz Großes entstanden!

EDIT: Der Editor hier ist ja gruselig. Lange nicht mehr sowas Schlimmes bedient :)

nRF52 support

even if the ESP (ESP32, ESP8266) are not supported, you helped me a lot to get the ESP32 running, but I'm still stuck with ESP32 battery usage and the sleep/idle function.
The biggest issues with the ESP MCU is there wake-up behavior (soft restart).
Thus I have decided to do futher investigations with the very power efficient nRF52 based boards such as the nRF52832 boards below (I have ordered some).
The advantage of this chip/barebone boards that has ultra low power capabilities (esp. build for that) and it has a lot of peripheral support and it does continue the code after the wakeup (like the other MCU's).
As I still would like to build a battery powered Homematic room sensor with E-Paper display, I would require your support.
BTW: THe nRF52832 has 512kB Flash and 64kB RAM and thus it does not run out of memory like the ATMEGA328p or others.

ANother question: Does the STM32 support include now full sleep sleep support or do I have the same issue as with the ESP32 (no sleep thus no battery mode support)?

https://de.aliexpress.com/item/nRF52832-2-4GHz-Wireless-rf-Module-CDSENET-E73-2G4M04S-SPI-SMD-rf-Receiver-transmitter-Bluetooth-Module/32819293925.html?spm=a2g0x.search0104.3.1.3b9652d4CsTYGo&ws_ab_test=searchweb0_0,searchweb201602_5_10065_10068_5014915_10547_10059_10548_10696_100031_10084_10083_10103_451_10618_5014815_452_10304_10307_10820_10821_10302,searchweb201603_1,ppcSwitch_3&algo_expid=d697b633-dade-447d-aa4c-9b0063c4aeb8-0&algo_pvid=d697b633-dade-447d-aa4c-9b0063c4aeb8&transAbTest=ae803_1&priceBeautifyAB=0

HM-SEC-RHS: no cycleInfoMsg

Hi! What a great project!

But I've got a (hopeful small) issue:

I'm using the HM-SEC-RHS.ino and after ~1 day the CCU says "Communication Error" with that device.

I took a look at the code and found that in line L100 the call of cycleInfoMsg(false); is commented out.

But whether with leaving it as it is or setting cycleInfoMsg(true);, the "Communication Error" appears.

IrqInternalBatt funktioniert nicht nach hal.sleep<>();

Hi,

vielleicht habe ich nur einen groben Denkfehler.
Folgendes kurzes Beispiel:

#define EI_NOTEXTERNAL
#include <EnableInterrupt.h>
#include <AskSinPP.h>
#include <LowPower.h>

#include <MultiChannelDevice.h>

#define LED_PIN           4
#define CONFIG_BUTTON_PIN 8

#define PEERS_PER_CHANNEL 6


// all library classes are placed in the namespace 'as'
using namespace as;

// define all device properties
const struct DeviceInfo PROGMEM devinfo = {
  {0xca, 0xfe, 0xde},     // Device ID
  "0101010101",           // Device Serial
  {0xca, 0xfe},           // Device Model Indoor
  0x10,                   // Firmware Version
  as::DeviceType::THSensor, // Device Type
  {0x01, 0x00}            // Info Bytes
};


typedef AvrSPI<10, 11, 12, 13> SPIType;
typedef Radio<SPIType, 2> RadioType;
typedef StatusLed<LED_PIN> LedType;
typedef AskSin<LedType, IrqInternalBatt, RadioType> Hal;
Hal hal;


class WeatherChannel : public Channel<Hal, List1, EmptyList, List4, PEERS_PER_CHANNEL, List0>, public Alarm {
  public:
    WeatherChannel () : Channel(), Alarm(5) {}
    virtual ~WeatherChannel () {}

    virtual void trigger (__attribute__ ((unused)) AlarmClock& clock) {
      tick = seconds2ticks(5);
      DPRINT("ALARM V= ");
      DDECLN(device().battery().current());
      clock.add(*this);
    }

    void setup(Device<Hal, List0>* dev, uint8_t number, uint16_t addr) {
      Channel::setup(dev, number, addr);
      sysclock.add(*this);
    }

    uint8_t status () const { return 0; }

    uint8_t flags  () const { return 0; }
};

typedef MultiChannelDevice<Hal, WeatherChannel, 1> WeatherType;
WeatherType sdev(devinfo, 0x20);
ConfigButton<WeatherType> cfgBtn(sdev);

void setup () {
  DINIT(57600, ASKSIN_PLUS_PLUS_IDENTIFIER);
  sdev.init(hal);
  hal.initBattery(60UL * 60, 24, 19);
  buttonISR(cfgBtn, CONFIG_BUTTON_PIN);
  sdev.initDone();
  while( hal.battery.current() == 0 ) ;
  DPRINTLN("INIT DONE");
}

void loop() {
  bool worked = hal.runready();
  bool poll = sdev.pollRadio();
  if ( worked == false && poll == false ) {
    hal.sleep<>();
  }
}

Alle 5 Sekunden wacht die AlarmClock auf und gibt die aktuelle Spannung aus.

ALARM V= 31
ALARM V= 31
...

Reduziere ich langsam am Labornetzgerät die Spannung, verändert sich nichts.
❌ Der initial beim Start gemessene Wert wird fortlaufend ausgegeben.
✅Entferne ich hal.sleep<>();, dann funktioniert es und der ausgegebene Spannungswert sinkt.

Nun die spannende Frage: Ist das nur bei mir so? Kann das jemand reproduzieren?

add new sensors

Hi papa,
kannst du bitte die beiden Sensor-Files für DS18B20 und BH1750 mit aufnehmen?
Ich musste die .h nach .txt umbenennen, um sie hier anhängen zu können...

Danke!
Bh1750.txt
Ds18b20.txt

AskSin++ for ESP MCU's (ESP32, ESP8266)

Hello, I urgently need a library to build homematic devices, which are not available by Homematic.
I was happy to find AskSin or AskSinPP.
I need to work with ESP (Espressif) MCU's preferable ESP32 and unfortunatly AskSinPP does not support it.
I have commented out alls avr/... libs, EnableInterrupt.h, LowPower.h, as they are all not compatible with Espressif MCU's. I guess they might also not required (as the ESP32 has featues already in the internal RTOS)?
So would it be possible to get a AskSinPP version which supports ESP32/ESP8266 MCU's which are the MCU's my friends and myself are using for mos projects?
I'm using boards like: WeMos Lolin32
https://www.aliexpress.com/item/4-MB-Flash-WEMOS-Lolin32-V1-0-0-WIFI-Bluetooth-Card-Based-ESP-32-ESP-WROOM/32823891656.html
https://www.aliexpress.com/item/LOLIN32-Wifi-Bluetooth-Development-Board-Antenna-ESP32-ESP-32-REV1-CH340-CH340G-MicroPython-Micro-USB-Lithium/32846143452.html
Anything I can do to create motivation (e.g sponsor you boards?) :-)

regards Heinz

LongPress not correctly working for blind actor

With my pullrequest #48 some bugs are fixed but there is still a racecondition.
First: The original actor doesn't send statusupdates when moving.

This are the messages from an original blind actor when doing a long press and release after some time

-> 0B 43 84 40 3B1630 4AA8CC 43 09 - 2595907
-> 0B 44 84 40 3B1630 4AA8CC 43 09 - 2596173
-> 0B 45 84 40 3B1630 4AA8CC 43 09 - 2596440
-> 0B 46 84 40 3B1630 4AA8CC 43 09 - 2596706
-> 0B 47 84 40 3B1630 4AA8CC 43 09 - 2596974
-> 0B 48 84 40 3B1630 4AA8CC 43 09 - 2597240
-> 0B 49 84 40 3B1630 4AA8CC 43 09 - 2597507
-> 0B 4A 84 40 3B1630 4AA8CC 43 09 - 2597773
-> 0B 4B 84 40 3B1630 4AA8CC 43 09 - 2598039
-> 0B 4C 84 40 3B1630 4AA8CC 43 09 - 2598305
-> 0B 4D 84 40 3B1630 4AA8CC 43 09 - 2598572
-> 0B 4E 84 40 3B1630 4AA8CC 43 09 - 2598838
-> 0B 4F 84 40 3B1630 4AA8CC 43 09 - 2599104
-> 0B 50 84 40 3B1630 4AA8CC 43 09 - 2599370
-> 0B 51 84 40 3B1630 4AA8CC 43 09 - 2599636
ignore 0B 52 A0 40 3B1630 4AA8CC 43 09 - 2599903
ignore 0E 52 80 02 4AA8CC 3B1630 01 01 9C 20 47 - 2600030
ignore 0D 53 A4 10 4AA8CC 473071 06 01 9A 00 - 2602391
ignore 0A 53 80 02 473071 4AA8CC 00 - 2602514

Because your code sends periodical statusupdates some longpress messages are missed or are processed to late. You can see that the longpress works until a statusupdate is send and than the longpress is interrupted because the actor switched to the next state.
You can get around this problem when you set a higher value for maxTimeFirstDir but 0,5 seconds is the default and 0,8 minimal seconds when you use aes.

-> 0B 4C 84 40 5667E7 5932AF 41 6A - 140406
Switch from 03 to 01
Switch from 01 to 02
-> 0B 4D 84 40 5667E7 5932AF 41 6A - 140673
Switch from 02 to 08
UP - 140679
<- 0E 36 A2 10 5932AF 473071 06 01 04 50 70 - 140793
-> 0A 36 80 02 473071 5932AF 00 - 140920
waitAck: 01
-> 0B 4E 84 40 5667E7 5932AF 41 6A - 140939
-> 0B 4F 84 40 5667E7 5932AF 41 6A - 141205
-> 0B 50 84 40 5667E7 5932AF 41 6A - 141471
-> 0B 51 84 40 5667E7 5932AF 41 6A - 141737
-> 0B 52 84 40 5667E7 5932AF 41 6A - 142004
-> 0B 53 84 40 5667E7 5932AF 41 6A - 142270
-> 0B 54 84 40 5667E7 5932AF 41 6A - 142534
<- 0E 37 A2 10 5932AF 473071 06 01 0D 50 70 - 142704
-> 0B 55 84 40 5667E7 5932AF 41 6A - 142809
-> 0A 37 80 02 473071 5932AF 00 - 142833
waitAck: 01
Switch from 08 to 03
STOP - 143034
-> 0B 56 84 40 5667E7 5932AF 41 6A - 143067
Switch from 03 to 01
Switch from 01 to 02
-> 0B 57 84 40 5667E7 5932AF 41 6A - 143333
Switch from 02 to 08
UP - 143339
<- 0E 38 A2 10 5932AF 473071 06 01 0D 50 6D - 143454
-> 0A 38 80 02 473071 5932AF 00 - 143579
waitAck: 01
-> 0B 58 84 40 5667E7 5932AF 41 6A - 143599
<- 0E 39 A2 10 5932AF 473071 06 01 0D 50 70 - 143722
-> 0A 39 80 02 473071 5932AF 00 - 143849
-> 0B 59 84 40 5667E7 5932AF 41 6A - 143865
-> 0B 5A A0 40 5667E7 5932AF 41 6A - 144132
<- 0E 5A 80 02 5932AF 5667E7 01 01 0D 50 6E - 144252
Switch from 08 to 03
STOP - 144633
<- 0E 3A A2 10 5932AF 473071 06 01 11 00 6E - 145362
-> 0A 3A 80 02 473071 5932AF 00 - 145489
waitAck: 01

HM-LC-SWX-SMX

Frage dazu.
Ich hab den Sketch geladen.
Habe folgendes im Sketch eingestellt:

// number of relays by defining the device
//#define HM_LC_SW1_SM 0x00,0x02
//#define HM_LC_SW2_SM 0x00,0x0a
#define HM_LC_SW4_SM 0x00,0x03

#define HM_SENSOR_RELAY
dann müsste doch der erste Part "angesprochen" werden.

#ifdef HM_SENSOR_RELAY
// relay pins for the HMSensor Relay Board
#define RELAY1_PIN 17
#define RELAY2_PIN 16
#define RELAY3_PIN 15
#define RELAY4_PIN 14
#define BUTTON1_PIN 6
#define BUTTON2_PIN 3
#define BUTTON3_PIN 19
#define BUTTON4_PIN 18
#else
// relay output pins compatible to the HM_Relay project
#define RELAY1_PIN 5
#define RELAY2_PIN 6
#define RELAY3_PIN 7
#define RELAY4_PIN 3
#endif

in HM erkennt er das Modul

grafik
Die Ausgänge schalten sauber über HM.
Nur dachte ich, dass ich dann mit den 4 Buttons die entsprechenden Ausgänge schalten kann, Aber da passiert nichts.
Oder bin ich da falsch. Acho Taster hab ich als schließer gegen GND an die PINS 3,6,18,19
Gruß Peter

Dimmer: 'WORKING' state wird bei "heller/dunkler"-Steuerung mittels internem Peering nicht zurückgesetzt

Wird über das interne Peering (ConfigToggleButton) das Dimmlevel schrittweise erhöht/verringert, bleibt der Status "WORKING" in der CCU stehen.

Was ich bisher erfassen konnte:
Steuerung über CCU:


Empfange 5% Dimmlevel
-> 0E 0F A0 11 4A80E8 010801 02 01 0A 00 A0  - 12451
Ramp/Level: 50/10
Bestätige mit WORKING
<- 0F 0F 80 02 010801 4A80E8 01 01 00 50 24 00  - 12580
Beende WORKING
<- 0F 07 A2 10 010801 4A80E8 06 01 0A 00 24 0A  - 15060
Erhalte Quittung
-> 0A 07 80 02 4A80E8 010801 00  - 15185
waitAck: 01

-> finaler Status ist korrekt.

Steuerung über Taster, Funktion: "Dimmer heller":

 debounce
 pressed
 released
-> 0B 08 02 40 010801 010801 01 08  - 88344

Neuer Dimmlevel wird an CCU gesendet inkl WORKING
<- 0F 09 A2 10 010801 4A80E8 06 01 14 20 26 14  - 90370

-> 0A 09 80 02 4A80E8 010801 00  - 90494
waitAck: 01

-> WORKING bleibt bestehen.

Steuerung über Taster, Funktion: "Dimmer ein":

 debounce
 pressed
 released
-> 0B 10 02 40 010801 010801 01 10  - 343898
Ramp/Level: 50/200

Neuer Dimmlevel wird an CCU gesendet; alles i.O. - kein WORKING State
<- 0F 11 A2 10 010801 4A80E8 06 01 C8 00 28 C8  - 346529

-> 0A 11 80 02 4A80E8 010801 00  - 346654
waitAck: 01

-> finaler Status ist korrekt.

Blind-Aktor fährt nicht korrekt auf Position wenn diese kleiner ist als die aktuelle

Wenn man eine Position anfahren will per gepeertem Taster und diese kleiner ist als die aktuelle, dann fährt das Rollo trotzdem hoch.
Problem ist hier, dass es aktuell keine Möglichkeit gibt in einem solchen Fall in den State AS_CM_JT_RAMPOFF zu wechseln, da der Wert für die Position ja in SHORT_ON_LEVEL bzw. LONG_ON_LEVEL gespeichert ist.

Beispiel 1:
Position: 0%
SHORT_ON_LEVEL: 20%
Rollo fährt auf 20% (korrekt)

Beispiel 2:
Position: 40%
SHORT_ON_LEVEL: 20%
Rollo fährt auf 60% (falsch)

Es muss so umgebaut werden, dass das destlevel nicht beim getDelayForState aus dem Registern gelesen wird, da ja noch garnicht fest steht wohin gefahren werden muss.

Ich würde getNextState in der BlindStateMachine überschreiben und das Setzen des destlevel aus der
Funktion getDelayForState entfernen.
Den Code habe ich noch nicht getestet. Vielleicht komme ich heute Nachmittag dazu ...

virtual uint8_t getNextState (uint8_t stat) {
    switch( stat ) {
      case AS_CM_JT_ONDELAY:  return AS_CM_JT_REFON;
      case AS_CM_JT_REFON:    
        destlevel = lst.onLevel();
        
        if(destlevel > level){
          return AS_CM_JT_RAMPOFF;
        }
        else {
          return AS_CM_JT_RAMPON;
        }
        
      case AS_CM_JT_RAMPON:   return AS_CM_JT_ON;
      case AS_CM_JT_ON:       return AS_CM_JT_OFFDELAY;
      case AS_CM_JT_OFFDELAY: return AS_CM_JT_REFOFF;
      case AS_CM_JT_REFOFF:   
        destlevel = lst.offLevel();
        
        if(destlevel < level){
          return AS_CM_JT_RAMPOFF;
        }
        else {
          return AS_CM_JT_RAMPON;
        }
      case AS_CM_JT_RAMPOFF:  return AS_CM_JT_OFF;
      case AS_CM_JT_OFF:      return AS_CM_JT_ONDELAY;
    }
    return AS_CM_JT_NONE;
  }

Erweiterung um Temperatur und Feuchtesensor SHT21 / Si7021

Ist es dir möglich, den Temperatur- und Feuchtesensor SHT21 / Si7021 einzubinden.
Er soll eine geringe Fehlertoleranz bei Feuchte aufweisen, wo der BME 280 ja etwas problematisch erscheint. Könnte dann mit dem BMP 280 arbeiten und den BME 280 ersetzen.

Viele Grüße Gerd

Config Freq nach RESET gelöscht?

Bootlog nachdem zuvor FreqTest ausgeführt wurde:

AskSin++ V4.1.0 (Aug 26 2019 00:17:46)
Address Space: 32 - 1650
CC init1
CC Version: 14
 - ready
Config Freq: 0x21657A
ID: 010801  Serial: papa010801 debounce
 pressed
 longpressed
 longpressed
RESET
AskSin++ V4.1.0 (Aug 26 2019 00:17:46)
Address Space: 32 - 1650
00000000
Init Storage: CAFE6963
CC init1
CC Version: 14
 - ready
ID: 010801  Serial: papa010801

Nach dem RESET wird Config Freq: 0x21657A nicht mehr ausgegeben. Bedeutet dies, dass die Freqenzanpassung gelöscht ist? Afair sollte das in der Config-Area gespeichert sein und einen RESET überleben?

Imeplement IrqExternalBatt

Könnte man die neue Batterie-Messung auch für die StepUp-Geräte implementieren und eine externe Messung vornehm? Spricht hier was dagegen oder gibt es Fallstricke?

Nicht alle Parameter sind per CCU konfigurierbar

Ich habe jetzt schon mehrere Aktoren gebaut und bei keinem kann ich z.B.

  • Reset per Gerätetaste sperren
  • Statusmeldungen Mindestverzögerung
  • Statusmeldungen Zufallsanteil
  • Max. Sendeversuche

Ich weiß, dass einige Funktionen nicht implementiert sind, aber ich würde doch sagen, dass sie konfigurierbar sein sollten.
Ich hab schon versucht mich schlau zu machen wodran die CCU erkennt welche Funktionen in der List1 angezeigt werden. Bin da aber leider noch nicht so weit gekommen.

Pairing issue

When I try pairing the HM-ES-TX-WM sketch I have to trigger pairing many many times until it works.
Sometimes I can the some dataexchange but it's not pairing.
Sometimes I got the message from Homematic that I want to pair a device over the serialnumber and I have to enter the securitycode.

When I then change the type of the sensor I have to trigger the update many many times, too (config button)

HM-SEN-MDIR-WM55 mit zusätzlichem Relais

Zu aller erst...... Super Projekt.
Dies ist kein Fehler, sondern ne Anfrage.
Verwende seither ESP8266 mit ESPEasy, IOBroker und CCU um meine "Wünsche" der Hausautomation zu realisieren, aber so wären manche Dinge wahrscheinlich stabiler.
Ich wollte fragen ob es möglich wäre dem HM-SEN-MDIR-WM55 zusätzlich zu den Tasten die in dem Sketch sind auch ein Relais Port mit ein zu binden?
Habe aktuell einen ESP mit PIR, BH1750, Taster und Relais, da aber komischerweise an dieser Stelle Wlan deutlich schlecht und der 868Mhz Empfang der CCU mit 70db deutlich stabiler ist, wäre es dann eine Alternative. Leider hab ich noch nicht so richtig den Code kapiert (was zum erweitern nötig wäre).

Gruß Peter

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.