Refactorisé encore une fois les nom de projet energy afin de pouvoir séparer le projet de l'installation solaire du toit et du sol

This commit is contained in:
Christian Zufferey
2020-06-03 20:18:55 +02:00
parent 7431eeb759
commit 5acd21666f
147 changed files with 3747 additions and 4 deletions

View File

@@ -1,8 +1,10 @@
# Mesure d'énergie d'une installation monophasée oldies
zf200603.1509
# Mesure d'énergie d'une installation monophasée
Version pour l'installation solaire qui se trouve sur le toit !
Ancienne version encore en production :-(
zf200603.2017
<!-- TOC titleSize:2 tabSpaces:2 depthFrom:1 depthTo:6 withLinks:1 updateOnSave:1 orderedList:0 skip:1 title:1 charForUnorderedList:* -->
## Table of Contents

View File

@@ -0,0 +1,187 @@
# Mesure d'énergie d'une installation monophasée
Version pour l'installation solaire qui se trouve sur le toit !
zf200603.2015
**ATTENTION:<br>
Ce README est parti d'un autre projet similaire, donc pas tout juste pour ce projet**
<!-- TOC titleSize:2 tabSpaces:2 depthFrom:1 depthTo:6 withLinks:1 updateOnSave:1 orderedList:0 skip:1 title:1 charForUnorderedList:* -->
## Table of Contents
* [Astuces de mesures de la puissance](#astuces-de-mesures-de-la-puissance)
* [Schéma](#schéma)
* [Astuces](#astuces)
* [Installation](#installation)
* [Utilisation](#utilisation)
* [Distribution des rôles de NodeMCU](#distribution-des-rôles-de-nodemcu)
* [Affichage des températures en local sur le NodeMCU](#affichage-des-températures-en-local-sur-le-nodemcu)
* [Affichage du petit serveur web du NodeMCU_Lua](#affichage-du-petit-serveur-web-du-nodemculua)
* [Modification du code source du NodeMCU en remote](#modification-du-code-source-du-nodemcu-en-remote)
* [Utilisation de la console du NodeMCU en remote](#utilisation-de-la-console-du-nodemcu-en-remote)
* [Visualisation sur ThingSpeak](#visualisation-sur-thingspeak)
<!-- /TOC -->
Petit projet pour mesurer la puissance d'un appareil électrique à partir de la mesure du courant avec un petit transformateur de courant qui se clips sur un conducteur avec un NodeMCU en LUA, et l'afficher sur Grafana avec une DB InfluxDB. Comme par exemple la production électrique d'une installation solaire photovoltaïque monophasée.
ATTENTION, dans ce projet, on ne tient pas compte du déphasage entre la tension et le courant (cos phy) !
![Image](https://raw.githubusercontent.com/zuzu59/NodeMCU_Lua/master/Mesures/energy/transfo_courant_clip_1p/img/20190908_134444.jpg)
Petit transformateur de mesure du courant avec un rapport de 1/800 avec l'épissure pour la boucle de mesure de courant !
![Image](https://raw.githubusercontent.com/zuzu59/NodeMCU_Lua/master/Mesures/energy/transfo_courant_clip_1p/img/20190908_221514.jpg)
C'est mon NodeMCU de banc tests, il y a un pont diviseur pour faire une masse fictive à +0.5V qui permet de mesurer les alternances négatives du courant et la résistance *convertisseur* de courant de la mesure en tension (U=R*I).
![Image](https://raw.githubusercontent.com/zuzu59/NodeMCU_Lua/master/Mesures/energy/transfo_courant_clip_1p/img/20190908_213927.jpg)
On voit ici l'image du courant d'un foehn (450W) en petite vitesse. On voit bien que la partie négative de l'alternance est effacée. C'est à cause de la mise ne série d'une diode avec le corps de chauffe du foehn, c'est un moyen très simple de diminuer le puissance.
![Image](https://raw.githubusercontent.com/zuzu59/NodeMCU_Lua/master/Mesures/energy/transfo_courant_clip_1p/img/20190908_213900.jpg)
On voit ici l'image du courant d'un foehn (450W) en grande vitesse. L'alternance est bien complète ici. On voit aussi qu'elle se trouve dans la plage des 1V du convertisseur ADC du NodeMCU grâce à l'astuce de la *masse fictive* de 0.5V.
![Image](https://raw.githubusercontent.com/zuzu59/NodeMCU_Lua/master/Mesures/energy/transfo_courant_clip_1p/img/20190907_170403.jpg)
Vue globale de mon installation solaire, pour l'instant posée sur le sol, de 2x panneaux de 280W :-)
![Image](https://raw.githubusercontent.com/zuzu59/NodeMCU_Lua/master/Mesures/energy/transfo_courant_clip_1p/img/20190907_170414.jpg)
Vue des deux onduleurs (un par panneau) qui injectent directement l'énergie produite dans le réseau électrique 220V de la maison.
<br><bR>
On peut voir ici, avec ce projet assez complet, toutes les possibilités offertes de la programmation des NodeMCU en LUA, en mode événementiel. <br>
Choses qui ne seraient pas possible si on l'avait fait en C++ (mode Arduino), comme par exemple:
* serveur WEB Active Server Pages ZYX, permet de faire des pages HTML dynamiques avec du code LUA in line. Les pages HTML sont sauve dans la FLASH du NodeMCU
* serveur WEB service pour le HUB concentrateur de mesures de différents NodeMCU (API GET)
* serveur WEB pour l'affichage de la consommation électrique
* serveur WEB pour l'IDE, modification du code source en remote directement depuis une page WEB, pas besoin d'IDE
* crontab, horloge pour les mesures
* serveur TELNET, utilisation de la console en remote pour le dépannage
Toutes les fonctions sont bien séparées dans des scripts, cela *complexifie* le projet mais ce qui facilite la portabilité entre les projets et aussi sa mise au point.
## Astuces de mesures de la puissance
Dans ce projet il y a 1x NodeMCU qui mesure la production électrique de mon installation solaire PV. On mesure le courant injecté dans le réseau électrique de la maison avec un petit transformateur de courant *clipsé* sur la phase du smart inverter.<br>
### Schéma
![Image](https://github.com/zuzu59/NodeMCU_Lua/blob/master/Mesures/energy/transfo_courant_clip_1p/schemas/sch%C3%A9ma.png?raw=true)
Le petit transfo de courant a un rapport de 25mA à 20A, soit 0.025/20=0.00125 soit encore 1/800.
Une masse virtuelle de 0.5V est constituée avec le pont des résistances R2/R1, cela permet de *remonter* la tension alternative de la mesure de courant.
La résistance R3 est utilisée pour la conversion courant/tension du transfo de courant.<br>
Pour une charge maximale de 600W, la résistance R3 est de 100R, et pour 1'200W elle est de 56R.
### Astuces
* Comme le convertisseur ADC du NodeMCU ne peut mesurer que des valeurs positives comprises entre 0V et 1V, on ajoute une masse *fictive* au signal du transformateur de courant de 0.5V afin de *remonter* l'alternance négative.<br>
Au lieu de *découper* la sinusoïde (50Hz) en 100 *parties*, c'est à dire toutes les 0.2ms (5'000x /s), pour en faire l'intégrale. On lit l'ADC toutes les 11ms (seulement 91x /s) donc beaucoup plus lentement.<br>
* Comme la sinusoïde fait 20ms et est *répétitive*, on balaye (par *décalage*) statistiquement la sinusoïde.<br>
* On *redresse* l'alternance par rapport à la masse fictive (env 0.5V), ce qui nous permet d'estimer une valeur RMS du courant quelque soit sa forme et on la moyenne sur une période de 2.1 secondes.<br>
* Les mesures min et max ne sont là juste que pour vérifier que nous sommes bien dans la plage de mesure avec le choix de la résistance de *conversion* du transformateur de courant.<br>
* Le calcul de la puissance mesurée est très simpliste, un simple ```P=U*I```. On ne tient donc pas compte ici du ```cos(phy)``` qui pourrait varier en fonction des charges inductives dans la maison !
## Installation
Il faut *flasher* le NodeMCU avec ce firmware:
https://github.com/zuzu59/NodeMCU_Lua/blob/master/Firmware/nodemcu-master-20-modules-2019-07-01-06-35-13-float.bin
Avec ces modules:
```
adc ds18b20 file gpio http i2c mdns mqtt net
node ow pcm rtctime sntp spi tmr uart wifi ws2812
```
## Utilisation
### Distribution des rôles de NodeMCU
Comme la mesure de production électrique est faite avec 1x NodeMCU, il y a donc 1x fichier de *secrets*. C'est dans ce fichier de *secrets* qu'il y a l'information de l'adresse IP de la base de donnée InfluxDB !<br>
```
secrets_energy.lua
```
**ATTENTION, readme pas encore terminé, il faut encore modifier le readme depuis ici ! zf190922.1740**
<br>
<br>
<br>
<br>
<br>
<br>
### Affichage des températures en local sur le NodeMCU
On peut lire la température directement sur le NodeMCU au moyen de cet url (il faut modifier l'adresse IP du NodeMCU en question):
nodemcu 28 int, http://192.168.0.171/disp_temp.html
nodemcu 29 sud, http://192.168.0.180/disp_temp.html
nodemcu 30 nord, http://192.168.0.105/disp_temp.html
### Affichage du petit serveur web du NodeMCU_Lua
Chaque NodeMCU a son propre serveur WEB, on peut l'accéder simplement depuis son adresse IP:
nodemcu 28 int, http://192.168.0.171
nodemcu 29 sud, http://192.168.0.180
nodemcu 30 nord, http://192.168.0.105
### Modification du code source du NodeMCU en remote
Très pratique pour le debug, on peut directement modifier le code source Lua du NodeMCU en remote avec cet url:
nodemcu 28 int, http://192.168.0.171:88
nodemcu 29 sud, http://192.168.0.180:88
nodemcu 30 sord, http://192.168.0.105:88
### Utilisation de la console du NodeMCU en remote
Très pratique pour le debug, on peut accéder à la console du NodeMCU en remote avec telnet:
nodemcu 28 int, **telnet -rN 192.168.0.171**
nodemcu 29 sud, **telnet -rN 192.168.0.180**
nodemcu 30 nord, **telnet -rN 192.168.0.105**
## Visualisation sur ThingSpeak
La totale en détail
https://thingspeak.com/channels/817940
Seulement la corrélation entre les trois température
https://thingspeak.com/apps/plugins/300559
pense bête:
```
file.open("hello.lua","w+")
file.writeline([[print("hello nodemcu")]])
file.writeline([[print(node.heap())]])
file.close()
```

View File

Before

Width:  |  Height:  |  Size: 1.5 MiB

After

Width:  |  Height:  |  Size: 1.5 MiB

View File

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

Before

Width:  |  Height:  |  Size: 768 KiB

After

Width:  |  Height:  |  Size: 768 KiB

View File

Before

Width:  |  Height:  |  Size: 801 KiB

After

Width:  |  Height:  |  Size: 801 KiB

View File

Before

Width:  |  Height:  |  Size: 792 KiB

After

Width:  |  Height:  |  Size: 792 KiB

View File

Before

Width:  |  Height:  |  Size: 834 KiB

After

Width:  |  Height:  |  Size: 834 KiB

View File

Before

Width:  |  Height:  |  Size: 399 KiB

After

Width:  |  Height:  |  Size: 399 KiB

View File

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 73 KiB

View File

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 90 KiB

View File

@@ -0,0 +1,27 @@
-- Petit scripts pour faire un flip flop avec le bouton et la led du nodemcu
-- Très intéressant la techno utilisée ici pour enlever les rebonds du micro switch
-- dans la variable b se trouve l'heure à laquelle l'interruption est arrivée, il suffit juste alors de lui mettre un petit délai de 300mS
print("\n 0_btn_flipflop.lua zf200216.1457 \n")
gpio.write(zLED,1) gpio.mode(zLED,gpio.OUTPUT)
gpio.mode(zBTN,gpio.INT)
d=tmr.now()
function zled (a,b,c)
--print("a: "..a..",b: "..b..",c: "..c)
if b-d > 300*1000 then
if verbose then
gpio.write(zLED, gpio.LOW) tmr.delay(10000) gpio.write(zLED, gpio.HIGH)
verbose=false
else
gpio.write(zLED, gpio.LOW) tmr.delay(200000) gpio.write(zLED, gpio.HIGH)
verbose=true
end
d=b
print("verbose:",verbose)
end
end
gpio.trig(zBTN, "down", zled)

View File

@@ -0,0 +1,40 @@
-- Petit script pour faire office de crontab pour les mesures
print("\n 0_cron.lua zf200603.1950 \n")
cron1=tmr.create()
cron1:alarm(10*1000, tmr.ALARM_AUTO, function()
if verbose then print("cron1........................") end
if verbose then gpio.write(zLED, gpio.LOW) tmr.delay(10000) gpio.write(zLED, gpio.HIGH) end
http_post(influxdb_url,"energy,memory=cron1_"..yellow_id.." ram="..node.heap())
-- f = "0_1_htu21d.lua" if file.exists(f) then dofile(f) end
-- http_post(influxdb_url,"energy,capteur=th1 temperature="..ztemp1)
-- http_post(influxdb_url,"energy,capteur=th1 humidity="..zhum1)
--
-- ztemp1=nil zhum1=nil ztemp2=nil zhum2=nil
-- f = "0_zdyndns.lua" if file.exists(f) then dofile(f) end
f=nil
if verbose then print("End cron:\n"..node.heap()) end
collectgarbage()
if verbose then print(node.heap()) end
end)
--[[
cron1:stop()
cron1:start()
sec, usec = rtctime.get()
print(sec,usec)
print(ztime_format(rtctime.get()))
]]

View File

@@ -0,0 +1,61 @@
-- Lit le convertisseur ADC connecté sur le transformateur de courant
-- pour mesurer le courant électrique de l'installation PV
print("\n 0_get_power.lua zf200603.2013 \n")
-- Astuce de mesure:
-- On converti le courant en tension avec la résistance de charge du
-- transformateur de courant 1/800 et le mesure avec l'ADC
-- Au lieu de découper la sinusoïde en 100 parties, c'est à dire toutes
-- les 0.2ms (5'000x /s), pour en faire l'intégrale. On lit l'adc toutes
-- les 11ms (91x /s) donc beaucoup plus lentement.
-- Comme la sinusoïde fait 20ms et est répétitive, on balaye (par décalage)
-- statistiquement la sinusoïde.
-- On redresse l'alternance par rapport à la masse fictive (env 0.5),
-- ce qui nous permet d'estimer une valeur RMS du courant
-- quelque soit sa forme et on le somme sur 2.1 secondes
-- Les mesures min et max ne sont là juste pour vérifier que nous sommes
-- bien dans la plage de mesure avec le choix de la résistance de conversion
-- la conversion courant/tension/puissance est faite avec une simple régle de 3
zpow_cal=692 --puissance mesurée de la charge étalon
zadc_cal=59 --valeur de l'adc pour zpow_cal
zadc_offset=172
zadc_sum=0 zadc_offset_sum=0 znb_mes=0
zadc_min=zadc_offset zadc_max=zadc_offset
if adc.force_init_mode(adc.INIT_ADC)
then
node.restart()
return
end
tmr_read_adc=tmr.create()
tmr_read_adc:alarm(11, tmr.ALARM_AUTO, function()
read_adc()
end)
tmr_calc_rms=tmr.create()
tmr_calc_rms:alarm(2.1*1000, tmr.ALARM_AUTO, function()
calc_rms()
end)
function read_adc()
zadc=adc.read(0)
if zadc<=zadc_min then zadc_min=zadc end
if zadc>=zadc_max then zadc_max=zadc end
zadc_offset_sum=zadc_offset_sum+zadc
zadc=zadc-zadc_offset if zadc<=0 then zadc=zadc*-1 end
zadc_sum=zadc_sum+zadc znb_mes=znb_mes+1
end
function calc_rms()
zadc_rms=math.floor(zadc_sum/znb_mes)
if zadc_rms<=8 then zadc_rms=0 end
zadc_offset=math.floor(zadc_offset_sum/znb_mes)
zpower=math.floor(zadc_rms*zpow_cal/zadc_cal)
if verbose then print(zadc_min,zadc_max,zadc_max-zadc_min,zadc_offset,zadc_rms,zpower.."W") end
zadc_min=zadc_offset zadc_max=zadc_offset
zadc_sum=0 zadc_offset_sum=0 znb_mes=0
zadc_min=zadc_offset zadc_max=zadc_offset
end

View File

@@ -0,0 +1,47 @@
-- Petit script pour envoyer en // es valeurs sur un serveur WEB (InfluxDB)
-- via un http POST à travers un FIFO
if verbose then print("\n 0_http_post.lua zf200527.1836 \n") end
t_zurl={} t_zarg={} f_zpost=false
function tprint(t)
for key,value in pairs(t) do print(key, value) end
end
function zpost()
f_zpost=true zurl=t_zurl[1] zarg=t_zarg[1]
if verbose then print("zurl: "..zurl) end if verbose then print("zarg: "..zarg) end
http.post(zurl, 'Content-Type: application/x-www-form-urlencoded\r\n', zarg, function(code, data)
if (code < 0) then
print("HTTP request failed")
print("zuzu", code, data)
else
if verbose then print(code, data) end
end
table.remove(t_zurl, 1) table.remove(t_zarg, 1)
if t_zurl[1]==nil then
f_zpost=false
else
zpost()
end
if verbose then print("End zpost:\n"..node.heap()) end
collectgarbage()
if verbose then print(node.heap()) end
end)
zurl=nil zarg=nil
end
function http_post(zurl,zarg)
table.insert(t_zurl, zurl) table.insert(t_zarg, zarg)
if verbose then print("t_zurl:") tprint(t_zurl) print("t_zarg:") tprint(t_zarg) end
if f_zpost==false then zpost() end
if verbose then print("End http_post:\n"..node.heap()) end
collectgarbage()
if verbose then print(node.heap()) end
end

View File

@@ -0,0 +1,197 @@
--[[
tests connection reverse telnet commande à faire tourner sur le GATEWAY !
1ere console
pour une liaison directe:
socat TCP-LISTEN:23043,fork,reuseaddr STDIO
pour une console sur un port:
socat TCP-LISTEN:23043,reuseaddr,fork TCP-LISTEN:23000,reuseaddr,bind=127.0.0.1
2e console
telnet -r localhost 23000
]]
--[[
tests connection reverse telnet commande à faire tourner sur le GATEWAY ET sur sa MACHINE !
1ere console sur le GATEWAY
socat TCP-LISTEN:23043,reuseaddr,fork TCP-LISTEN:23000,reuseaddr,bind=127.0.0.1
2e console sur sa MACHINE
ssh -L 23000:localhost:23000 user@GATEWAY
3e console sur sa MACHINE (~.return pour sortir !)
telnet -r localhost 23000
ou sur MAC
telnet -rN localhost 23000
]]
print("\n 0_tst3_socat.lua zf200530.1132 \n")
local node, table, tmr, uwrite, tostring =
node, table, tmr, uart.write, tostring
local function telnet_listener(socket)
local insert, remove, concat, heap, gc =
table.insert, table.remove, table.concat, node.heap, collectgarbage
local fifo1, fifo1l, fifo2, fifo2l = {}, 0, {}, 0
local s -- s is a copy of the TCP socket if and only if sending is in progress
local wdclr, cnt = tmr.wdclr, 0
local function debug(fmt, ...)
if (...) then fmt = fmt:format(...) end
uwrite(0, "\r\nDBG: ",fmt,"\r\n" )
cnt = cnt + 1
if cnt % 10 then wdclr() end
end
local function flushGarbage()
if heap() < 13440 then gc() end
end
local function sendLine()
if not s then return end
if fifo2l + fifo1l == 0 then -- both FIFOs empty, so clear down s
s = nil
return
end
flushGarbage()
if #fifo2 < 4 then -- Flush FIFO1 into FIFO2
insert(fifo2,concat(fifo1))
fifo2l, fifo1, fifo1l = fifo2l + fifo1l, {}, 0
end
local rec = remove(fifo2,1) .. (remove(fifo2,1) or '') ..
(remove(fifo2,1) or '') .. (remove(fifo2,1) or '')
fifo2l = fifo2l - #rec
flushGarbage()
s:send(rec)
end
local F1_SIZE = 256
local function queueLine(str)
while #str > 0 do -- this is because str might be longer than the packet size!
local k, l = F1_SIZE - fifo1l, #str
local chunk
if #fifo1 >= 32 or (k < l and k < 16) then
insert(fifo2, concat(fifo1))
fifo2l, fifo1, fifo1l, k = fifo2l + fifo1l, {}, 0, F1_SIZE
end
if l > k+16 then -- also tolerate a size overrun of 16 bytes to avoid a split
chunk, str = str:sub(1,k), str:sub(k+1)
else
chunk, str = str, ''
end
insert(fifo1, chunk)
fifo1l = fifo1l + #chunk
end
if not s and socket then
s = socket
sendLine()
else
flushGarbage()
end
end
local function receiveLine(s, line)
node.input(line)
end
local function disconnect(s)
--fifo1, fifo1l, fifo2, fifo2l, s = {}, 0, {}, 0, nil
fifo1, fifo1l, fifo2, fifo2l, s = nil, nil, nil, nil, nil
--insert, remove, concat, heap, gc = nil, nil, nil, nil, nil
--wdclr, cnt = nil, nil
node.output(nil)
print("disconnected...")
-- print("rt_retry:",rt_retry)
-- rt_retry=rt_retry-1
-- print("rt_retry:",rt_retry)
-- if rt_retry>=0 then
print("on ressaie en vitesse une fois ;-)")
rt_connect()
-- end
end
--zzz
local function zconnection(s)
print("Welcome on ne devrait jamais passer par là to NodeMCU world.")
end
socket:on("connection", zconnection)
socket:on("receive", receiveLine)
socket:on("disconnection", disconnect)
socket:on("sent", sendLine)
node.output(queueLine, 0)
end
--net.createServer(net.TCP, 180):listen(23, telnet_listener)
print("Revers telnet server running...\n")
function rt_connect()
if verbose then
gpio.write(zLED, gpio.HIGH)
print("trying connect to "..console_host..":"..console_port)
print(node.heap()) collectgarbage() print(node.heap())
end
srv_rt = nil srv_rt = net.createConnection(net.TCP, 0)
srv_rt:on("connection", function(sck)
if verbose then
print("connected on "..console_host..":"..console_port)
print(node.heap()) collectgarbage() print(node.heap())
end
telnet_listener(sck)
print("Welcome to NodeMCU world.")
end)
srv_rt:connect(console_port,console_host)
end
tmr_socat1=tmr.create()
tmr_socat1:alarm(15*1000, tmr.ALARM_AUTO , function()
rt_retry=1
-- if verbose then gpio.write(zLED, gpio.LOW) tmr.delay(10000) gpio.write(zLED, gpio.HIGH) end
if srv_rt~=nil then
if console_port == srv_rt:getpeer() then
--cela tourne...
if verbose then gpio.write(zLED, gpio.LOW) end
else
--on relance...
rt_connect()
end
else
--on relance...
rt_connect()
end
end)
rt_retry=3
rt_connect()
--[[
tmr_socat1:unregister()
for k,v in pairs(_G) do print(k,v) end
print(srv_rt:getpeer())
srv_rt:connect(console_port,console_host)
gpio.write(zLED, gpio.LOW) tmr.delay(10000) gpio.write(zLED, gpio.HIGH)
if console_port == srv_rt:getpeer() then
gpio.write(zLED, gpio.LOW)
else
gpio.write(zLED, gpio.HIGH)
end
]]

View File

@@ -0,0 +1,33 @@
-- Petit script pour s'inregistrer sur zdyndns
function send_zdyndns()
if verbose then print("\n 0_zdyndns.lua zf200525.1403 \n") end
zip = wifi.sta.getip()
zdyndns_str = "s "..node_id..","..console_host..":"..tostring(console_port).." "..zip.."\n"
if verbose then print("zdyndns_str: /"..zdyndns_str.."/") end
srv_zdyndns = net.createConnection(net.TCP, 0)
srv_zdyndns:on("receive", function(conn, pl)
print("receiving...")
print(pl)
end)
srv_zdyndns:on("connection", function(sck)
if verbose then print("connected & sending...") end
sck:send(zdyndns_str, function(sk)
sk:close()
if verbose then print("close...") end
zdyndns_str=nil zip=nil srv_zdyndns=nil send_zdyndns=nil
if verbose then print("End zdyndns:\n"..node.heap()) end
collectgarbage()
if verbose then print(node.heap()) end
end)
end)
srv_zdyndns:connect(zdyndns_port,zdyndns_host)
end
send_zdyndns()

View File

@@ -0,0 +1 @@
{"url": "https://docs.google.com/open?id=11-Oi9YwTZ40iYweaWgdMLpXaym2wD_JAwgkQ-rwHABQ", "doc_id": "11-Oi9YwTZ40iYweaWgdMLpXaym2wD_JAwgkQ-rwHABQ", "email": "christian.zufferey@gmail.com"}

View File

@@ -1,6 +1,8 @@
# Mesure d'énergie d'une installation monophasée
zf200603.1940
Version pour l'installation solaire qui se trouve sur le sol !
zf200603.2016
**ATTENTION:<br>
Ce README est parti d'un autre projet similaire, donc pas tout juste pour ce projet**

View File

@@ -0,0 +1,37 @@
-- Petit script pour configurer les secrets dans ce projet
-- et que l'on n'aimerait pas être exportés sur Internet (github)
-- Il faut donc modifier le .gitignore avec secrets*.lua
-- il faut le renommer en 'secrets_project.lua' et sera exécuté
-- par 'wifi_init.lua' au moment du boot
-- pour récupérer l'ID de son NodeMCU il faut faire:
-- print(node.chipid())
function secrets_project()
print("\n secrets_project.lua zf200131.1058 \n")
zLED=4 -- NodeMCU
--zLED=7 -- SonOff
zBTN=3
node_id = "generic"
if node.chipid() == 6734851 then node_id = "sonoff_1" zLED=7 end
if node.chipid() == 16110605 then node_id = "sonoff_2" zLED=7 end
if node.chipid() == 3049119 then node_id = "adc_1" end
if node.chipid() == 3048906 then
node_id = "bolo_1"
thingspeak_url="http://api.thingspeak.com/update?api_key=kkk&"
end
if node.chipid() == 3049014 then
node_id = "tst_temp_1"
thingspeak_url="http://api.thingspeak.com/update?api_key=kkk&"
end
print("node_id: "..node_id)
end
secrets_project()
secrets_project=nil
--[[
=node.chipid()
]]

View File

@@ -0,0 +1,18 @@
-- Petit script pour configurer les secrets utilisés pour le wifi
-- et que l'on n'aimerait pas être exportés sur Internet (github)
-- Il faut donc modifier le .gitignore avec eus_params* et secret*
-- il faut le renommer en 'secrets_wifi.lua' et sera exécuté
-- par 'wifi_init.lua' une fois pour la configuration du WIFI
function secrets_wifi()
print("\n secrets_wifi.lua zf191222.2002 \n")
f= "eus_params.lua" if file.exists(f) then p = dofile(f) end
if p ~= nil then
cli_ssid = p.wifi_ssid cli_pwd = p.wifi_password p=nil
else
cli_ssid = "" cli_pwd = ""
end
ap_ssid="NodeMCU" ap_pwd="ppp"
end
secrets_wifi()

View File

@@ -0,0 +1,316 @@
# Quelques commandes remote (luatool) à envoyer avec le plugin Atom-IDE-terminal de l'éditeur Atom
# zf200527.1853
Todo à faire pour ce projet !
- faire la documentation pour le fonctionnement de concept de rtelnet dans un fichier à part .md
- y regarder pour faire tourner en MEME temps le reverse et le forward telnet
- z lancement ou arrêt du WEBIDE via la home page
v- ajouter fonction restart dans z_index.html (ATTENTION avec un argument restart, pas besoin de faire une page restart.html !)
v- ajouter l'adresse du zdyndns dans les secrets projets
v- ajouter l'affichage du node_id dans z_index.html
v- ajouter le web_srv2 dans boot au lieu de boot2
v- ajouter un état du RELAY et de la LED dans z_index.html
v- ajouter une page affichage variables globales
v- améliorer api_sonoff.html, il faut ajouter 'home' sur la page
v- améliorer le résultat de api_sonoff.html, il faut sortir l'état des IO lors d'un changement comme confirmation
v- arrêter de demander de connecter le WIFI automatiquement en mode station juste après le boot dans la config wifiinit (automatic connect)
v- clignoter la led à chaque mesure en fonction de verbose
v- copier secrets_project et secrets_wifi dans _secrets_project_ _secrets_wifi_ pour la documentation
v- déplacer le mode AP dans wifi_init
v- enlever la ligne wifi init dans z_index.html
v- faire la page web service pour allumer la LED
v- faire la page web service pour allumer le relay
v- faire que send_data et read_temp soient lancés à la volée afin d'économiser de la RAM quand ce n'est pas utilisé
v- garder variable node_id pour identification après poweron général, reattribution adrs ip sur modem 4G
v- if verbose print partout dans *.lua
v- le wifi setup ne fonctionne toujours pas quand il y a déjà un ap de connecté (problème du reboot quand adrs ip ok)!
v- mettre le numéro jaune du nodemcu dans les secrets projet et prendre 23000+num_jaune comme numéro de port pour le reverse telnet
v- passer à 10 secondes la seconde chance
v- passer à 15x les tentatives de connexions au WIFI
v- refaire le fichier _secrets_project.lua_ à partir de secrets_project.lua
v- regarder pour mettre "Welcome to NodeMCU world." quand connected, en fait quand on arrive dans le telnet_listener après la redirection du port série !
v- se connecter sur le zdyndns avec le numéro du port du telnet reverse utilisé
v- terminer la page .html affichage de la température et de l'humidité
v- terminer le reverse telnet ;-)
v- trouver un moyen pour configurer la lED dans initz.lua sans le rendre dangereux en cas de problème (éviter le reflashing en cas de reboot loop)
v- utiliser le bouton pour piloter le verbose
v- vérifier le fonctionnement d'allumer la LED, car ne marche plus !
x- ajouter argument ok dans wifi_init.html (sécurité)
x- mettre ZLED2 et ZRELAY dans secrets_project
# si luatool ne marche pas sur le MAC, il faut lire ceci:
# https://docs.google.com/document/d/1q64uK3IMOgEDdKaIAttbYuFt4GuLQ06k3FLeyfCsWLg/edit#heading=h.bmefcu67uwj0
# raccourcis clavier
# CTRL+ALT+ENTER envoie au terminal la ligne de l'éditeur
# SHIT+CTRL+` ouvre le terminal (attention, ne pas oublier de copier le *path* dans le *tree* et le changer)
# ALT+CMD+F bascule entre le terminal et l'éditeur
# définitions à faire AVANT !
export luatool_tty="/dev/cu.wchusbserial1410"
export zIP="192.168.0.182"
export zport="23"
export zIP="localhost"
export zport="23000"
ATTENTION: voir les tunnels tout à la fin !
# ouvrir et fermer (ALT+N+.) une session telnet sur le NodeMCU avec l'adresse zIP)
telnet -rN $zIP $zport
~.
--node.restart()
collectgarbage()
=node.heap()
for k,v in pairs(_G) do print(k,v) end
################################
# commandes lua pour ce projet #
################################
ssh ubuntu@www.zuzu-test.ml killall -9 socat
killall -9 ssh
ssh ubuntu@www.zuzu-test.ml socat TCP-LISTEN:23043,reuseaddr,fork TCP-LISTEN:23000,reuseaddr,bind=127.0.0.1 &
watch -n 1 'ssh ubuntu@www.zuzu-test.ml netstat -nat |grep 230'
ALT+CMD+F CTRL+C ALT+CMD+F
ssh -N -L 23000:localhost:23000 ubuntu@www.zuzu-test.ml &
export zIP="localhost"
export zport="23000"
telnet -rN $zIP $zport
verbose=false
for k,v in pairs(_G) do print(k,v) end
verbose=true
~.
#zdyn
./luatool.py --ip $zIP:$zport -f boot.lua
./luatool.py --ip $zIP:$zport -f z_index.html
./luatool.py --ip $zIP:$zport -f 0_send_data.lua
./luatool.py --ip $zIP:$zport -f 0_cron.lua
./luatool.py --ip $zIP:$zport -f 0_http_post.lua
./luatool.py --ip $zIP:$zport -f 0_htu21d.lua
./luatool.py --ip $zIP:$zport --zrestart
./luatool.py --ip $zIP:$zport -f api_sonoff.html
http://192.168.0.182
./luatool.py --ip $zIP:$zport -f dir.lua
telnet -rN $zIP $zport
verbose=false
verbose=true
~.
=node.heap()
collectgarbage()
=node.heap()
dofile("dir.lua")
dir()
for k,v in pairs(_G) do print(k,v) end
dofile("wifi_info.lua")
node.restart()
~.
./luatool.py --ip $zIP:$zport -f head.lua
telnet -rN $zIP $zport
dofile("head.lua")
zhead("boot.lua")
verbose=true
verbose=false
zsort_rssi() zshow()
#commandes luatool pour ce projet le .137 est à jour avec la nouvelle version du wifi !
~.
./luatool.py --ip $zIP:$zport -l
./luatool.py --ip $zIP:$zport -f wifi_init.lua
./luatool.py --ip $zIP:$zport -f secrets_wifi.lua
./luatool.py --ip $zIP:$zport -f initz.lua -t init.lua
./luatool.py --ip $zIP:$zport -f boot.lua
./luatool.py --ip $zIP:$zport -f boot2.lua
./luatool.py --ip $zIP:$zport -f wifi_init.lua
./luatool.py --ip $zIP:$zport -f set_time.lua
./luatool.py --ip $zIP:$zport -f wifi_info.lua
./luatool.py --ip $zIP:$zport -f c.lua
./luatool.py --ip $zIP:$zport -f cat.lua
./luatool.py --ip $zIP:$zport -f flash_led_xfois.lua
./luatool.py --ip $zIP:$zport -f head.lua
./luatool.py --ip $zIP:$zport -f b.lua
./luatool.py --ip $zIP:$zport -f web_srv2.lua
./luatool.py --ip $zIP:$zport -f z_index.html
./luatool.py --ip $zIP:$zport -f wifi_get_conf.html
./luatool.py --ip $zIP:$zport -f wifi_set_conf.html
./luatool.py --ip $zIP:$zport -f z_page1.html
./luatool.py --ip $zIP:$zport -f z_page2.html
./luatool.py --ip $zIP:$zport -f z_page3.html
./luatool.py --ip $zIP:$zport -f z_page4.html
./luatool.py --ip $zIP:$zport --delete wifi_ap_start.lua
./luatool.py --ip $zIP:$zport --delete wifi_cli_conf.lua
./luatool.py --ip $zIP:$zport --delete wifi_cli_start.lua
./luatool.py --ip $zIP:$zport --delete dir.lua
./luatool.py --ip $zIP:$zport --delete initz.lua
./luatool.py --ip $zIP:$zport --delete wifi_conf.lua
dofile("wifi_info.lua")
--node.restart()
for k,v in pairs(_G) do print(k,v) end
t=12
t=nil
print(pcall(function () print("2"..t) end))
# ici c'est maintenant ;-)
~.
./luatool.py --ip $zIP:$zport -f b.lua
#./luatool.py --ip $zIP:$zport --zrestart
telnet -rN $zIP $zport
zsort_rssi() zshow()
print(ztrig_rssi)
ztrig_rssi=-1000
ztrig_rssi=-90
# test de la gestion des erreurs
~.
./luatool.py --ip $zIP:$zport -f c.lua
#./luatool.py --ip $zIP:$zport --zrestart
telnet -rN $zIP $zport
status, err = pcall(function () dofile("c.lua") end) if status==false then print("Error: ",err) end
zerr=nil
zerr=1
ztmr_tst_err:unregister()
ztmr_tst_err:unregister()
for k,v in pairs(_G) do print(k,v) end
./luatool.py --ip $zIP --zrestart
# faire un cat d'un fichier sur le NodeMCU
dofile("cat.lua")
cat("boot2.lua")
# commandes luatool
./luatool.py -h
./luatool.py --ip $zIP:$zport -i
./luatool.py --ip $zIP:$zport -l
./luatool.py --ip $zIP:$zport -f toto.lua -d
./luatool.py --ip $zIP:$zport --delete toto.lua
****************************************************************************
# création des tunnels ssh
ATTENTION: dans un premier terminal !
Pour Bolo à Ruchonnet:
ssh -t -L 2323:localhost:2323 ubuntu@www.zuzu-test.ml ssh -N -L 2323:192.168.8.102:23 ubuntu@localhost -p 20223
Pour le Crêt
ssh -N -L 2323:192.168.0.137:23 admin@z.zufferey.com -p 1822
ssh -N -L 2323:192.168.0.122:23 admin@z.zufferey.com -p 1822
ssh -N -L 2323:192.168.0.118:23 admin@z.zufferey.com -p 1822
ATTENTION: dans un deuxième terminal !
export zIP="localhost"
export zport="2323"
telnet -rN $zIP $zport
~.
=node.heap()
verbose=false
verbose=true
dofile("dir2.lua")
dir()
filec("head.lua")
dofile("head.lua")
zhead("dir2.lua")
dofile("cat.lua")
cat("head.lua")
~.
--node.restart()
=node.heap()
status, err = pcall(function () fonction_a_tester() end) if status==false then print("Error: ",err) end
status, err = pcall(function () toto() end) if status==false then print("Error: ",err) end
Gestion de la passerelle SSH reverse
Puis depuis une autre console on peut faire directement pour aller sur l'OpiZ (ici le 20223):
ssh -t ubuntu@www.zuzu-test.ml ssh ubuntu@localhost -p 20223
ou
1ère console
On établit le tunnel local avec l'OpiZ
ssh -N -L 20223:localhost:20223 ubuntu@www.zuzu-test.ml
2ème console, on utilise le tunnel OpiZ en local sur sa machine
pour aller sur l'OpiZ
ssh ubuntu@localhost -p 20223
pour copier sa clef SSH depuis un MAC
./ssh-copy-id -i ~/.ssh/id_rsa.pub 'ubuntu@localhost -p 20223'
après on devrait pouvoir se connecter sans devoir entrer son password à chaque fois
ssh ubuntu@localhost -p 20223
ou, on établit un tunnel pour telnet sur un NodeMCU
ssh -L 2323:192.168.0.137:23 ubuntu@localhost -p 20223
puis
telnet -rN localhost 2323
ou, on établit un tunnel pour le rpimonotor sur l'OpiZ
ssh -N -L 8888:192.168.0.113:8888 ubuntu@localhost -p 20223
puis
http://localhost:8888
ou, on établit un tunnel proxy Socket 5 pour le modem 4G HUAWEI sur l'OpiZ
ssh -N -D 8080 ubuntu@localhost -p 20223
puis depuis le browser FireFox avec le plugin FoxyProxy Socket 5 sur localhost port 8080
http://192.168.8.1
.

View File

@@ -0,0 +1,38 @@
-- Scripts à charger après le boot pour démarrer son projet
print("\n boot.lua zf200603.1953 \n")
-- function ztime_stamp() return tmr.now()/1000000 end
function boot()
verbose = false
print("On lance le boot...")
print(node.heap()) collectgarbage() print(node.heap())
f = "0_http_post.lua" if file.exists(f) then dofile(f) end
http_post(influxdb_url,"energy,memory=boot_"..yellow_id.." ram="..node.heap())
-- f="0_tst3_socat.lua" if file.exists(f) then dofile(f) end
-- f = "0_zdyndns.lua" if file.exists(f) then dofile(f) end
-- print(node.heap()) collectgarbage() print(node.heap())
f="0_btn_flipflop.lua" if file.exists(f) then dofile(f) end
-- print(node.heap()) collectgarbage() print(node.heap())
f="0_get_power.lua" if file.exists(f) then dofile(f) end
-- f="0_cron.lua" if file.exists(f) then dofile(f) end
print("verbose:",verbose) print("boot lancé...")
gpio.write(zLED, gpio.HIGH)
f=nil boot=nil
print(node.heap()) collectgarbage() print(node.heap())
end
boot()
--[[
verbose = true
verbose = false
]]

View File

@@ -0,0 +1,18 @@
-- fonction cat() pour afficher le contenu d'un fichier dans la flash
print("\n cat.lua zf192026.0858 \n")
function cat(zfile)
print("\n"..zfile.."\n-------------------------------")
zfilei = file.open(zfile, "r")
i=1
zline=file.readline()
repeat
-- print(i..": "..string.sub(zline,1,string.len(zline)-1))
print(string.sub(zline,1,string.len(zline)-1))
i=i+1 zline=file.readline()
until zline== nil
file.close(zfilei)
print("-------------------------------")
end

View File

@@ -0,0 +1,31 @@
-- fonction dir() pour juste afficher les fichiers avec leur taille
print("\n dir2.lua zf191223.1455 \n")
function dir()
local zdir={}
local pfile = file.list()
for k,v in pairs(pfile) do
zdir[#zdir+1] = k..string.rep(" ",24-string.len(k)).." : "..v
end
table.sort(zdir) for i=1, #zdir do print(zdir[i]) end
size_file=nil chksum_file=nil k=nil
end
dir()
print("\nusage:")
print(" dir()")
--[[
dir()
dirc()
filec("dir2.lua")
=node.heap()
clear_dir()
=node.heap()
for k,v in pairs(_G) do print(k,v) end
status, err = pcall(function () print(zhash("il était une fois trois petits cochons roses...")) end) if status==false then print("Error: ",err) end
]]

View File

@@ -0,0 +1 @@
-- programme pour faire un test depuis de le webide

View File

@@ -0,0 +1 @@
-- programme pour faire un test depuis de le webide

View File

@@ -0,0 +1 @@
-- programme pour faire un test depuis de le webide

View File

@@ -0,0 +1 @@
-- programme pour faire un test depuis de le webide

View File

@@ -0,0 +1,6 @@
-- Scripts pour afficher toutes les variables et fonctions en cours dans le système
print("\n a_tst_variable.lua zf190310.1525 \n")
for n in pairs (_G) do print(n) end

View File

@@ -0,0 +1,37 @@
-- Scripts juste pour allumer ou éteindre une LED sur un ruban RGB
-- tout sur la couleur: https://www.w3schools.com/colors/default.asp
-- roue des couleurs: https://iro.js.org/?ref=oldsite
print("\n led_rgb.lua zf190303.1436 \n")
nbleds=3
ws2812.init()
myLedStrip = ws2812.newBuffer(nbleds, 3)
function RGB_clear()
myLedStrip:fill(0, 0, 0) ws2812.write(myLedStrip)
end
function RGB_reform(R1, G1, B1) --conversion de RGB à BRG
rR1=B1 rG1=R1 rB1=G1
end
function zled_rgb(num_led, R1, G1, B1, zpower)
RGB_reform(R1, G1, B1)
myLedStrip:set(num_led, rR1*zpower, rG1*zpower, rB1*zpower)
ws2812.write(myLedStrip)
end
function zled_write()
ws2812.write(myLedStrip)
end
RGB_clear()
--[[
zled_rgb(1,255,0,0,1)
zled_rgb(2,0,255,0,1)
zled_rgb(2,0,255,0,0.05)
zled_rgb(3,0,0,255,1)
]]

View File

@@ -0,0 +1,12 @@
-- pour effacer TOUS les fichiers qui se trouve dans la flash du NodeMCU
print("\n rm_files.lua zf180907.1511 \n")
l=file.list() i=0
for k,v in pairs(l) do
i=i+v
file.remove(k)
end
print("-------------------------------")
print("\nC'est tout effaced :-) \n")

View File

@@ -0,0 +1,27 @@
ohm,%
33,100
36,96.77419355
41,92.74193548
45,88.70967742
52,84.67741935
56,80.64516129
61,76.61290323
67,72.58064516
72,68.5483871
79,64.51612903
83,60.48387097
91,56.4516129
97,52.41935484
104,48.38709677
112,44.35483871
117,40.32258065
121,36.29032258
128,32.25806452
132,28.22580645
139,24.19354839
150,20.16129032
166,16.12903226
191,12.09677419
207,8.064516129
224,4.032258065
240,0
1 ohm %
2 33 100
3 36 96.77419355
4 41 92.74193548
5 45 88.70967742
6 52 84.67741935
7 56 80.64516129
8 61 76.61290323
9 67 72.58064516
10 72 68.5483871
11 79 64.51612903
12 83 60.48387097
13 91 56.4516129
14 97 52.41935484
15 104 48.38709677
16 112 44.35483871
17 117 40.32258065
18 121 36.29032258
19 128 32.25806452
20 132 28.22580645
21 139 24.19354839
22 150 20.16129032
23 166 16.12903226
24 191 12.09677419
25 207 8.064516129
26 224 4.032258065
27 240 0

View File

@@ -0,0 +1,19 @@
-- Démarre le WIFI en mode AP
function wifi_ap_start()
print("\n wifi_ap_start.lua zf190310.1511 \n")
local zmodewifi=wifi.getmode()
if zmodewifi == wifi.NULLMODE then
print("WIFI mode AP only")
wifi.setmode(wifi.SOFTAP)
elseif zmodewifi == wifi.STATION then
print("WIFI mode AP+CLI")
wifi.setmode(wifi.STATIONAP)
end
wifi.ap.config({ ssid = "NodeMCU "..wifi.ap.getmac(), pwd = "12345678" })
--f= "wifi_info.lua" if file.exists(f) then dofile(f) end
end
wifi_ap_start()
wifi_ap_start=nil

View File

@@ -0,0 +1,12 @@
-- Petit script pour obtenir l'adresse IP du NodeMCU connecté sur un AP Wifi
print("\n wifi_get_ip.lua zf181119.2318 \n")
wifitimer1=tmr.create()
tmr.alarm(wifitimer1, 1000, tmr.ALARM_AUTO , function()
if wifi.sta.getip() == nil then
print("Connecting to AP...")
else
tmr.stop(wifitimer1)
f= "wifi_info.lua" if file.exists(f) then dofile(f) end
end
end)

View File

@@ -0,0 +1,9 @@
-- Déconnecte le WIFI
print("\n wifi_off.lua zf180822.0959 \n")
wifi.setmode(wifi.NULLMODE)
--[[
print(wifi.NULLMODE, wifi.STATION, wifi.SOFTAP, wifi.STATIONAP)
print(wifi.getmode())
]]

View File

@@ -0,0 +1,19 @@
-- fonction cat() pour afficher les 10 premières lignes d'un fichier dans la flash
print("\n head.lua zf192028.1516 \n")
function zhead(zfile)
print("\n"..zfile.."\n-------------------------------")
zfilei = file.open(zfile, "r")
i=1
zline=file.readline()
repeat
-- print(i..": "..string.sub(zline,1,string.len(zline)-1))
print(string.sub(zline,1,string.len(zline)-1))
i=i+1 zline=file.readline()
if i>10 then break end
until zline==nil
file.close(zfilei)
print("-------------------------------")
end

Some files were not shown because too many files have changed in this diff Show More