{"id":16144964,"url":"https://github.com/hallard/denky-d4","last_synced_at":"2025-03-18T17:31:55.981Z","repository":{"id":149039294,"uuid":"359859195","full_name":"hallard/Denky-D4","owner":"hallard","description":"Denky D4 WiFi Teleinfo","archived":false,"fork":false,"pushed_at":"2023-11-19T17:18:57.000Z","size":7285,"stargazers_count":15,"open_issues_count":0,"forks_count":1,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-03-14T14:30:34.196Z","etag":null,"topics":["d4","denky","esp32","tasmota","teleinfo","tic"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hallard.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-04-20T15:11:46.000Z","updated_at":"2025-02-04T20:42:31.000Z","dependencies_parsed_at":null,"dependency_job_id":"ea05ff69-4abd-4583-8977-0005ad548e96","html_url":"https://github.com/hallard/Denky-D4","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hallard%2FDenky-D4","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hallard%2FDenky-D4/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hallard%2FDenky-D4/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hallard%2FDenky-D4/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hallard","download_url":"https://codeload.github.com/hallard/Denky-D4/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243944714,"owners_count":20372850,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["d4","denky","esp32","tasmota","teleinfo","tic"],"created_at":"2024-10-10T00:14:37.806Z","updated_at":"2025-03-18T17:31:54.437Z","avatar_url":"https://github.com/hallard.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Denky D4 ESP32 Teleinfo\n\n\u003cimg src=\"https://github.com/hallard/Denky-D4/blob/main/pictures/Denky-D4-red.png\" alt=\"Denky D4\"\u003e\n\nThis board is used to get French energy meter called Teleinfo (AKA TIC) and has the following features:\n\n- Steroid ESP32 using ESP32-PICO-V3-02 chip with 8Mb Flash and 2Mb PSRAM\n- Serial to USB onboard converter\n- Teleinfo Reader interface\n- RGB User Led\n- Blue LED to see if Teleinfo signal is received\n- QWIIC/STEMMA I2C header sensors connector\n- USB-C Connector\n\nIt is a plug and play board, nothing to solder or assemble.\n\n# History\n\n**New in v1.3a**\n\n- Changed TIC trimmer from 1K to 2K\n- Changed TIC Led (blue) resistor to decrease light intensity\n- Placed easy cutting trace to disable Teleinfo Blue LED\n- Added exposed pad for 5V and GND to external powering out of USB connector\n\n\n**v1.3**\n\n- Changed some silk for better reading\n\n**v1.2**\n\n- Replaced R3 by a trimmer to allow TIC sensitivity change without soldering resistors\n\n**v1.1**\n\n- Changed CPU now use ESP32-PICO-V3-02 with 8Mb Flash and 2Mb PSRAM\n- Changed USB/SERIAL chip to CH9102 due to shortage\n- Added footprint for U-FL connector for external antenna \n- Removed headers pins\n- Reduced RGB LED size using SK6805-1515\n- Added small visual blue LED on Teleinfo receive signal\n- All components on same side (nothing on bottom side)\n\n**v1.0**\n\n- First fully working prototype\n\n# Detailed Description\n\nLook at the schematics for more informations, easy to understand. Wiring is as follow:\n\n| Pin Function | ESP32-PICO | \n|  :---        |  :---:  | \n| Téléinfo Rx  |  GPIO8  | \n| RGB Led      |  GPIO14 | \n| I2C SDA      |  GPIO21 | \n| I2C SDL      |  GPIO22 | \n\n\n# Schematics\n\n\u003cimg src=\"https://github.com/hallard/Denky-D4/blob/main/pictures/Denky-D4-sch.png\" alt=\"Denky D4 Schematics\"\u003e\n\n# Boards\n\n\u003cimg src=\"https://github.com/hallard/Denky-D4/blob/main/pictures/Denky-D4.jpg\" alt=\"Denky D4 Size\"\u003e\n\n\u003cimg src=\"https://github.com/hallard/Denky-D4/blob/main/pictures/Denky-D4-Boards.png\" alt=\"Denky D4 Boards\"\u003e\n\n\n# Firmware \n\nIt's compatible with Arduino IDE, Visual Studio Code and also Micro Python since this board use same CPU than Adafruit [QT-PY-ESP32-PICO](https://learn.adafruit.com/adafruit-qt-py-esp32-pico)\n\nYou can write your own and use with [LibTeleinfo](https://github.com/hallard/LibTeleinfo) library I wrote if you want to get rid of driving teleinfo stuff (chekout some [examples](ttps://github.com/hallard/LibTeleinfo/tree/master/examples)).\n\n## Tasmota\n\nBut I strongly suggest using amazing [Tasmota](https://tasmota.github.io/docs/) firmware, all is already done and well done.\n\nPlease check Teleinfo official tasmota [documentation](https://tasmota.github.io/docs/Teleinfo/) so see how to configure your device depending on smartmeter type and what options you need.\n\n### Nicolas's builds\n\nNicolas @NicolasBernaerts has made awesome changes on Tasmota to be able to show graph of consumption, history and other great features such has:\n\n- Ecowatt server to publish RTE Ecowatt signals\n- TCP server to live stream teleinfo data\n- FTP server to easily retrieve graph data\n\nYou can find more information on his dedicated [repo](https://github.com/NicolasBernaerts/tasmota/tree/master/teleinfo) and also ready made build for this Denky D4 board.\n\n### Tasmota Unofficial builds\n\nTeleinfo is not member of official Tasmota builds. So you need to build your own with `USE_TELEINFO` define. \nBut Tasmota team agreed it's not simple to build for end users, and they now provide unofficial build that follow developement branch, this mean you always have an up to date build with latest code available. Of course we added Teleinfo (ESP8266 and ESP32) builds in this unofficial build process so you have nothing to install and compile/link (building). You can't go easier.\n\nAnd as a cherry on the cake, easy flasher tools (web version and executable one) will present Teleinfo firmware so you are able to flash teleinfo firmware in less than 1 minute. You can check detail [here](https://github.com/Jason2866/Tasmota-specials) but here how to do that.\n\n- Launch [Web Flasher here](https://jason2866.github.io/Tasmota-specials/) \n- Select Teleinfo \n- Select Serial port, and click `install`\n\n\u003cimg src=\"https://github.com/hallard/WeMos-TIC/raw/master/pictures/WeMos-TIC-web_flasher.png\"\u003e\n\nOnce done something like that\n\n\u003cimg src=\"https://github.com/hallard/WeMos-TIC/raw/master/pictures/WeMos-TIC-web_flasher_ok.png\"\u003e\n\nAfter flashed, you should now see a new access point named `tasmota_aabbcc_xxxx` where you can connect to configure your WiFi for the device to connect on.\n\nAlternatively, if you connect serial console and reset the device you should see Serial logs like that\n```\n00:00:00.003 HDW: ESP32-D0WDQ6 \n00:00:00.037 UFS: FlashFS mounted with 308 kB free\n00:00:00.109 CFG: Loaded from File, Count 12\n00:00:00.124 QPC: Count 1\n00:00:00.257 CFG: no '*.autoconf' file found\n00:00:00.263 BRY: Berry initialized, RAM used=3620\n00:00:00.282 BRY: no 'preinit.be'\n00:00:00.291 Project tasmota - Tasmota Version 10.0.0.3(teleinfo)-2_0_1_1(2021-11-30T14:22:47)\n00:00:00.379 BRY: no 'autoexec.be'\n00:00:00.447 WIF: WifiManager active for 3 minutes\n00:00:01.139 HTP: Web server active on tasmota-090F8C-3980 with IP address 192.168.4.1\n00:00:06.827 QPC: Reset\n```\n\nIf you want to deep into this process or just curious, you can check out it's [here](https://github.com/Jason2866/Tasmota-specials)\n\n:memo: If you have some issues flashing with Web Flasher, do not hesitate to use another awesome tool [ESP Flasher](https://github.com/Jason2866/ESP_Flasher), with this one you can see exactly what's going on in case of issue because it has built in console. Usefull also after reboot of the device because console still active. This is the one I'm using day by day. In this case you need to download firmware to flash first [here](https://github.com/Jason2866/Tasmota-specials/tree/firmware/firmware/tasmota/other). Download firmware `tasmota-teleinfo`\n\nYou can take a look on `autoconf` [folder](https://github.com/tasmota/autoconf/tree/main/raw/esp32/Wemos_Teleinfo) to see some of init commands used on Denky D4.\n\n:memo: Don't forget to reset Energy counters on first boot with console command `EnergyTotal 0` if you have erratic values. \n\n\n### I2C Display\n\nYou can add fancy I2C display (or even I2C sensors), using the on board QWIIC sensor, please refer to section [I2C Display](https://github.com/hallard/WeMos-TIC/blob/master/README.md#i2c-display).\n\n### Autoconf \n\nAnother awesome feature of Tasmota is the ability to download configuration profile, and guess what, we done it for Denky D4, just go to configuration option, select Autoconfig and then choose in the list `Denky D4 V1.1` and here you are, ne need to copy/paste template, it's done by autoconfig.\nIf you want to deep into this process or just curious, you can check out it's [here](https://github.com/tasmota/autoconf)\n\n\n### Tasmota template\n\nI strongly suggest using awesome Tamsota autoconf feature but if you need Tasmota template for Denky D4, here it it\n\n#### V1.1 and up\n```json\n{\"NAME\":\"Denky D4 (v1.1)\",\"GPIO\":[32,0,0,0,1,0,0,0,0,1,1376,1,0,0,0,0,0,640,608,0,0,0,0,0,0,0,5632,0,0,0,0,0,0,0,0,0],\"FLAG\":0,\"BASE\":1}\n```\n\n#### V1.0\n```json\n{\"NAME\":\"Denky D4 (v1.0)\",\"GPIO\":[32,0,0,0,1,0,0,0,0,1,0,1,0,0,0,0,0,640,608,0,0,450,449,448,0,0,5632,0,0,0,0,0,0,0,0,0],\"FLAG\":0,\"BASE\":1}\n```\n\n## Berry Scripting \n\nNow you can personalize code with [Berry language](https://tasmota.github.io/docs/Berry/). Check out some Berry samples [here](https://github.com/arendst/Tasmota/blob/development/tasmota/berry/examples/)\n\nYou can do that by going to Berry console from Tasmota WEB user interface.\n\n### Drive RGB LED depending on actual power\n\nHere is a Berry example, goal is to follow real time consumption driving on board RGB Led depending on current Power consumption (low green then going to red when reaching maximum current of your contract)\n\n```python\n#-\n# example of using Berry script to change the led color\n# accordingly to power consumption\n# using Denky or WeMos Teleinfo (French Teleinfo reader)\n-#\n\n#- define the global symbol for reference -#\nruncolor = nil\n\ndef runcolor()\n  var max_contrat = 30 # contrat 30A\n  var i = energy.current\n  #print(i)\n  var red = tasmota.scale_uint(int(i), 0, max_contrat, 0, 255)\n  var green = 255 - red\n  var channels = [red, green, 0]\n  light.set({\"channels\":channels, \"bri\":64, \"power\":true})\n  tasmota.set_timer(2000, runcolor)\nend\n\n#- run animation -#\nruncolor()\n```\n\n### Send data to Emoncms with Berry \n\nWhat's magic with Berry is the ability to do basic stuff with data, in this example we will intercept MQTT send message by Energy driver, do some calc and send data to Emoncms every 15 seconds and also to drive RGB Led from Green (low load) to Red (approach max subscription)\n\nModifiy API key with your, and copy paste the following code into Berry Console. Tst and validate if all is okay for you.\n\nOnce all is fine, you paste the code into a file named `autoexec.be` on the Tasmota Filesystem so it will be executed each time Tasmota device starting.\n\n#### Mode Historique (contrat heures creuses)\n\n```python\nimport json\n\nvar api_url = \"https://emoncms.org/input/post\"\nvar api_key = \"YOUR_EMON_API_WRITE_KEY\"\nvar node_name = \"NODE_NAME\"\nvar post_every = 15000 # post evert 15 seconds\nvar payload = {}\n\ndef send_emoncms()\n  # Convert JSON object to string \n  var obj_json = json.dump(payload)\n\n  # Create URL to call\n  var param=\"?fulljson=\"+obj_json + \"\u0026node=\"+node_name + \"\u0026apikey=\"+api_key \n  # Post Data to EMONCMS\n  var cl = webclient()\n  cl.begin( api_url + param)\n  var r =  cl.GET()\n  tasmota.set_timer(post_every, send_emoncms)\nend\n\ndef setcolor(iinst, isousc)\n  var red = tasmota.scale_uint(iinst, 0, isousc, 0, 255)\n  var green = 255 - red\n  var channels = [red, green, 0]\n  light.set({\"channels\":channels, \"bri\":64, \"power\":true})\nend\n\n# set global payload the field we need\ndef rule_tic(value, trigger)\n  # Got Heures Creuses contract so I will calculate total consumption\n  # adding Heures Creuses (HCHC) + Heures Pleines (HCHP) and create new value for emoncms \n  # Change label depending on name for your contract type\n  var htot = value['HCHP'] + value['HCHC'] # mode historique\n  # Create new value HTOT converted to kWH\n  payload['HTOT'] = htot / 1000.0\n  # Calculate current percent Load \n  var iinst = value['IINST']  # mode historique\n  var isousc= value['ISOUSC'] # mode historique\n\n  if iinst != nil \u0026\u0026 isousc != nil \n    # Drive RGB LED\n    setcolor(iinst, isousc)\n    if isousc \u003e 0\n      load = 100 * iinst / isousc\n      payload['LOAD'] = load\n    end\n  end\n\n  # Set values we need to send to emoncms\n  payload['ADCO']  = value['ADCO']\n  payload['HCHP']  = value['HCHP']\n  payload['HCHC']  = value['HCHC']\n  payload['ISOUSC']= isousc\n  payload['PAPP']  = value['PAPP']\n  payload['IINST'] = iinst\n\nend\n\ndef start()\n  # Callback on each frame interception\n  tasmota.add_rule(\"TIC\",rule_tic)\n  # fire 1st post in 5s \n  tasmota.set_timer(5000, send_emoncms)\nend\n\n# delay start to have time to get full frame\ntasmota.set_timer(10000, start)\n\n```\n\n\n#### Mode Standard (contrat heures creuses)\n\n```python\nimport json\n\nvar api_url = \"https://emoncms.org/input/post\"\nvar api_key = \"YOUR_EMON_API_WRITE_KEY\"\nvar node_name = \"NODE_NAME\"\nvar post_every = 15000 # post evert 15 seconds\nvar payload = {}\n\ndef send_emoncms()\n  # Convert JSON object to string \n  var obj_json = json.dump(payload)\n\n  # Create URL to call\n  var param=\"?fulljson=\"+obj_json + \"\u0026node=\"+node_name + \"\u0026apikey=\"+api_key \n  # Post Data to EMONCMS\n  var cl = webclient()\n  cl.begin( api_url + param)\n  var r =  cl.GET()\n  tasmota.set_timer(post_every, send_emoncms)\nend\n\ndef setcolor(iinst, isousc)\n  var red = tasmota.scale_uint(iinst, 0, isousc, 0, 255)\n  var green = 255 - red\n  var channels = [red, green, 0]\n  light.set({\"channels\":channels, \"bri\":64, \"power\":true})\nend\n\n# set global payload the field we need\ndef rule_tic(value, trigger)\n  # Got Heures Creuses contract so I will calculate total consumption\n  # Calculate current percent Load \n  var iinst = value['IRMS1']  \n  var isousc= value['PREF']*5 \n\n  if iinst != nil \u0026\u0026 isousc != nil \n    # Drive RGB LED\n    setcolor(iinst, isousc)\n    if isousc \u003e 0\n      load = 100 * iinst / isousc\n      payload['LOAD'] = load\n    end\n  end\n\n  # Here I keep name of historique mode\n  payload['ADCO']  = value['ADSC']\n  payload['HTOT']  = value['EAST'] / 1000 # I need kWh\n  payload['HCHP']  = value['EASF01']\n  payload['HCHC']  = value['EASF02']\n  payload['ISOUSC']= isousc\n  payload['PAPP']  = value['SINSTS']\n  payload['IINST'] = iinst\n\nend\n\ndef start()\n  # Callback on each frame interception\n  tasmota.add_rule(\"TIC\",rule_tic)\n  # fire 1st post in 5s \n  tasmota.set_timer(5000, send_emoncms)\nend\n\n# delay start to have time to get full frame\ntasmota.set_timer(10000, start)\n\n```\n\n\n### Custom WEB Interface\n\nIf you are not happy with values on the WEB interface you can totaly change them to fit your needs.\n\nYou can add new values to display or disable all values displayed and use you own or even some calculated ones.\n\nTo disable all current values displayed please use the following command in console (not the berry one)\n\n```\nbacklog0 WebSensor0 0 ; WebSensor1 0 ; WebSensor2 0 ; WebSensor3 0\n```\n\nThen you can add Teleinfo driver (this one as example) into a file named `teleinfo.be`\n\nThis is just an example please fill it to your needs. This one display Total `EAST` index, `URMS1` and `IRMS1` on web interface\n\n\n```python\n# Teleinfo driver written in Berry\n# Support for Teleinfo custom values from choosen fields returned by smart meter\n \nclass TELEINFO: Driver\n\n  # Global var Needed\n  var east\n  var irms\n  var urms\n\n  def init()\n    # initialize globals\n\n    # Don't display original sensors on WebUI, we want just our ones\n    tasmota.cmd(\"backlog0 WebSensor0 0 ; WebSensor1 0 ; WebSensor2 0 ; WebSensor3 0\")\n\n    # create rules to trigger when Teleinfo values updates \n    # Use Teleinfo Etiquette Names to get whatever value you need\n    tasmota.add_rule(\"TIC#EAST\", /value -\u003e self.trigger_east(value))\n    tasmota.add_rule(\"TIC#IRMS1\", /value -\u003e self.trigger_irms(value))\n    tasmota.add_rule(\"TIC#URMS1\", /value -\u003e self.trigger_urms(value))\n  end\n\n  def trigger_east(index)\n    self.east = index\n  end\n\n  def trigger_irms(i)\n    self.irms = i\n    # DEBUG print(\"irms:\", i)\n  end\n\n  def trigger_urms(u)\n    self.urms = u\n    # DEBUG print(\"urms:\", u)\n  end\n\n  # trigger a read every second \n  def every_second()\n    # DEBUG print(\"sensors:\",tasmota.read_sensors())\n  end\n\n  # display sensor value in the web UI\n  def web_sensor()\n    import string\n    var msg = string.format(\n            \"{s}Consommation{m}%d Wh{e}\"\n            \"{s}Tension RMS{m}%d V{e}\"\n            \"{s}Intensité RMS{m}%d A{e}\", \n             self.east, self.urms, self.irms )\n\n    tasmota.web_send_decimal(msg)\n  end\n\nend\n\n# Instantiate the driver\nteleinfo = TELEINFO()\n# add it to Tasmota\ntasmota.add_driver(teleinfo)\n\n```\n\nThen you need to load and start it into your `autoexec.be` file. just add followin at the end of the file\n\n```python\n# Auto start teleinfo driver\nload(\"teleinfo.be\")\n```\n\n#### Here how it looks like\n\n\u003cimg src=\"https://github.com/hallard/Denky-D4/blob/main/pictures/Denky-D4-tasmota-custom-ui.png\" alt=\"Denky D4 Custom User Interface\"\u003e\n\n\n# Support and discussion\n\nIf you have any issue or just want to discuss on this project, please use community [forum](https://community.ch2i.eu/category/20)\n\n# License\n\n\u003cimg alt=\"Creative Commons Attribution-NonCommercial 4.0\" src=\"https://i.creativecommons.org/l/by-nc/4.0/88x31.png\"\u003e   \n\nThis work is licensed under a [Creative Commons Attribution-NonCommercial 4.0 International License](http://creativecommons.org/licenses/by-nc/4.0/)    \nIf you want to do commercial stuff with this project, please contact [CH2i company](https://ch2i.eu/en#support) so we can organize an simple agreement.\n\n# Lazy building your own? \n\nYou can order this module (V1.3a only) fully assembled with some extra on [tindie][1]\n\n\u003ca href=\"https://www.tindie.com/products/28907/\"\u003e\u003cimg src=\"https://d2ss6ovg47m0r5.cloudfront.net/badges/tindie-mediums.png\" alt=\"I sell on Tindie\" width=\"150\" height=\"78\"\u003e\u003c/a\u003e\n\n# Misc\n\nSee news and other projects on my [blog][2] \n \n[1]: https://www.tindie.com/products/25467/\n[2]: https://hallard.me\n\n\n\n\n\n\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhallard%2Fdenky-d4","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhallard%2Fdenky-d4","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhallard%2Fdenky-d4/lists"}