Refactorisation de noms de projets en cours

- dupliqué le projet energy 1 phase pour le projet mesure déshumidificateur à Ruchonnet
- créé le nouveau projet level, mesure d'eau dans un bidon à Ruchonnet
This commit is contained in:
Christian Zufferey
2020-06-24 18:56:12 +02:00
parent a843ae1631
commit 904221563b
152 changed files with 8902 additions and 0 deletions

View File

@@ -0,0 +1,370 @@
2020/06/11 11:45:26
4
2020/06/11 11:46:05
4
2020/06/11 11:49:14
4
2020/06/11 11:54:10
4
2020/06/11 11:57:55
4
2020/06/11 12:14:37
3
2020/06/11 12:46:56
3
2020/06/11 13:03:17
3
2020/06/11 13:19:37
3
2020/06/11 13:29:21
4
2020/06/11 13:40:35
4
2020/06/11 13:57:15
3
2020/06/11 14:08:44
4
2020/06/11 14:25:15
4
2020/06/11 14:28:34
4
2020/06/11 14:45:10
3
2020/06/11 15:01:34
3
2020/06/11 15:19:40
4
2020/06/11 15:27:50
4
2020/06/11 15:29:12
4
2020/06/11 15:45:34
4
2020/06/11 15:48:51
4
2020/06/11 16:05:32
3
2020/06/11 16:19:49
4
2020/06/11 16:23:57
4
2020/06/11 16:40:45
4
2020/06/11 16:54:53
4
2020/06/11 16:58:53
4
2020/06/11 17:00:31
4
2020/06/11 17:03:18
4
2020/06/11 17:06:44
4
2020/06/11 17:11:19
4
2020/06/11 17:28:00
3
2020/06/11 17:44:22
3
2020/06/11 18:00:56
3
2020/06/11 18:17:30
3
2020/06/11 18:33:23
4
2020/06/11 18:50:14
3
2020/06/11 19:06:37
3
2020/06/11 19:21:19
4
2020/06/11 19:23:49
4
2020/06/11 19:28:44
4
2020/06/11 19:34:24
3
2020/06/11 19:39:58
3
2020/06/11 19:45:35
3
2020/06/11 19:47:22
6
2020/06/11 19:53:14
3
2020/06/11 19:58:44
3
2020/06/11 20:06:06
4
2020/06/11 20:11:45
3
2020/06/11 20:19:06
4
2020/06/11 20:24:49
3
2020/06/11 20:30:39
3
2020/06/11 20:36:14
3
2020/06/11 20:41:51
3
2020/06/11 20:47:28
3
2020/06/11 20:53:05
3
2020/06/11 20:58:56
3
2020/06/11 21:06:14
4
2020/06/11 21:11:56
3
2020/06/11 21:17:34
3
2020/06/11 21:23:10
3
2020/06/11 21:28:47
3
2020/06/11 21:34:29
3
2020/06/11 21:40:21
3
2020/06/11 21:45:58
3
2020/06/11 21:51:40
3
2020/06/11 21:57:12
3
2020/06/11 22:02:58
3
2020/06/11 22:08:27
3
2020/06/11 22:14:08
3
2020/06/11 22:19:45
3
2020/06/11 22:25:23
3
2020/06/11 22:31:04
3
2020/06/11 22:36:37
3
2020/06/11 22:42:25
3
2020/06/11 22:49:45
4
2020/06/11 22:55:22
3
2020/06/11 23:01:12
3
2020/06/11 23:06:47
3
2020/06/11 23:12:26
3
2020/06/11 23:18:03
3
2020/06/11 23:23:44
3
2020/06/11 23:29:34
3
2020/06/11 23:35:09
3
2020/06/11 23:40:51
3
2020/06/11 23:46:26
3
2020/06/11 23:52:06
3
2020/06/11 23:59:22
4
2020/06/12 00:05:01
3
2020/06/12 00:20:36
3
2020/06/12 00:26:12
3
2020/06/12 00:31:48
3
2020/06/12 00:37:38
3
2020/06/12 00:43:13
3
2020/06/12 00:49:01
3
2020/06/12 00:56:21
4
2020/06/12 01:02:22
3
2020/06/12 01:08:24
3
2020/06/12 01:14:19
3
2020/06/12 01:19:57
3
2020/06/12 01:25:30
3
2020/06/12 01:31:06
3
2020/06/12 01:36:44
3
2020/06/12 01:42:21
3
2020/06/12 01:47:54
3
2020/06/12 01:53:32
3
2020/06/12 01:59:08
3
2020/06/12 02:04:47
3
2020/06/12 02:10:22
3
2020/06/12 02:16:01
3
2020/06/12 02:21:37
3
2020/06/12 02:27:09
3
2020/06/12 02:32:49
3
2020/06/12 02:38:23
3
2020/06/12 02:44:01
3
2020/06/12 02:49:37
3
2020/06/12 02:55:13
3
2020/06/12 03:00:54
3
2020/06/12 03:06:28
3
2020/06/12 03:12:06
3
2020/06/12 03:17:40
3
2020/06/12 03:23:31
3
2020/06/12 03:29:07
3
2020/06/12 03:34:45
3
2020/06/12 03:42:18
4
2020/06/12 03:47:57
3
2020/06/12 03:53:32
3
2020/06/12 04:00:56
4
2020/06/12 04:06:35
3
2020/06/12 04:12:29
3
2020/06/12 04:18:12
3
2020/06/12 04:23:59
3
2020/06/12 04:29:36
3
2020/06/12 04:35:18
3
2020/06/12 04:40:51
3
2020/06/12 04:46:32
3
2020/06/12 04:52:06
3
2020/06/12 04:57:42
3
2020/06/12 05:03:18
3
2020/06/12 05:08:53
3
2020/06/12 05:14:36
3
2020/06/12 05:20:10
3
2020/06/12 05:25:45
3
2020/06/12 05:31:21
3
2020/06/12 05:36:59
3
2020/06/12 05:47:32
3
2020/06/12 05:53:10
3
2020/06/12 05:58:46
3
2020/06/12 06:04:24
3
2020/06/12 06:11:42
4
2020/06/12 06:19:07
4
2020/06/12 06:26:49
4
2020/06/12 06:32:39
3
2020/06/12 06:38:15
3
2020/06/12 06:43:53
3
2020/06/12 06:51:11
4
2020/06/12 06:56:51
3
2020/06/12 07:02:28
3
2020/06/12 07:08:04
3
2020/06/12 07:13:45
3
2020/06/12 07:19:36
3
2020/06/12 07:25:14
3
2020/06/12 07:30:50
3
2020/06/12 07:36:27
3
2020/06/12 07:42:06
3
2020/06/12 07:47:56
3
2020/06/12 07:53:40
3
2020/06/12 07:59:19
3
2020/06/12 08:05:00
3
2020/06/12 08:10:45
3
2020/06/12 08:16:54
3
2020/06/12 08:22:28
3
2020/06/12 08:29:50
4
2020/06/12 08:35:36
3
2020/06/12 08:41:12
3
2020/06/12 08:47:00
3
2020/06/12 08:52:41
3
2020/06/12 08:58:15
3
2020/06/12 09:03:52
3
2020/06/12 09:09:26
3
2020/06/12 09:15:05
3
2020/06/12 09:20:45
3
2020/06/12 09:26:19
3
2020/06/12 09:29:45
4

View File

@@ -0,0 +1,28 @@
-- 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 zf200621.1942 \n")
gpio.write(zLED,1) gpio.mode(zLED,gpio.OUTPUT)
gpio.mode(zBTN,gpio.INT)
btn_time=tmr.now()
function z_btn_led (a,b,c)
--print("a: "..a..",b: "..b..",c: "..c)
if b-btn_time > 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
btn_time=b
print("verbose:",verbose)
end
end
gpio.trig(zBTN, "down", z_btn_led)

View File

@@ -0,0 +1,37 @@
-- Petit script pour faire office de crontab pour les mesures
print("\n 0_cron.lua zf200621.1936 \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
rt_launch()
-- http_post(influxdb_url,"energy,value=test1_"..yellow_id.." val=1")
-- http_post(influxdb_url,"energy,memory=cron1_"..yellow_id.." ram="..node.heap())
-- if yellow_id == 60 then http_post(influxdb_url,"energy,compteur=3 puissance="..zpower/1000) end
if yellow_id == 64 then http_post(influxdb_url,"energy,compteur=4 puissance="..zpower/1000) end
-- http_post(influxdb_url,"energy,value=test2_"..yellow_id.." val=2")
-- http_post(influxdb_url,"energy,value=test3_"..yellow_id.." val=3")
-- http_post(influxdb_url,"energy,value=test4_"..yellow_id.." val=4")
-- f = "0_zdyndns.lua" if file.exists(f) then dofile(f) end
-- f=nil
-- if verbose then print("End cron:") end
collectgarbage()
-- if verbose then print(node.heap()) end
end)
--[[
cron1:stop()
cron1:start()
]]

View File

@@ -0,0 +1,52 @@
-- fonction dir_vers() pour afficher toutes les versions de tous les fichiers *.lua sur le NodeMCU !
-- fonction filec(fichier) pour afficher la version d'un seul fichiers sur le NodeMCU !
function dir3()
print("\n 0_dir3.lua zf200611.1714 \n")
function file_vers(name_file)
local z=""
if string.find(name_file,"%.lua") then
z=name_file..":"
-- print("fichier: "..name_file)
local f,i1,i2,j1,j2,k,t = f,i1,i2,j1,j2,k,t
f = file.open(name_file, "r")
while true do
local t = f:readline() if t == nil then break end
-- recherche de l'entête de version [print("\n ]
-- ATTENTION, il faut échapper la '(' avec un % et convertir le '\' en char(92)
k='print%("'..string.char(92)..'n '
i1,j1 = string.find(t,k)
if i1 ~= nil then
k=string.char(92)..'n"%)'
i2,j2 = string.find(t,k,j1)
z=name_file..": "..string.sub(t,j1+1,i2-2)
break
end
end
f:close()
uart.write(0,".")
end
return z
end
zdir={} list_files={}
local k,v = k,v local pfile = file.list()
for k,v in pairs(pfile) do
zdir[#zdir+1] = file_vers(k)
end
table.sort(zdir) for i=1, #zdir do print(zdir[i]) end
dir_vers=nil file_vers=nil list_files=nil zdir=nil
dir3=nil
end
dir3()
--[[
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,63 @@
-- 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 zf200621.1143 \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 verbose then print(zadc_sum,znb_mes,zadc_rms) end
if zadc_rms<=4 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(node.heap()) end
-- 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,45 @@
-- 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 zf200621.2320 \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 local zurl=t_zurl[1] local zarg=t_zarg[1]
-- zarg=zarg.."\n".."energy,value=nb_waiting_"..yellow_id.." val="..#t_zurl
zarg=zarg.."\n".."energy,memory=zpost_"..yellow_id.." ram="..node.heap()
-- 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)
if debug_rec~=nil then debug_rec("HTTP request failed: ", code, data) end
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:") end
collectgarbage()
-- if verbose then print(node.heap()) end
end)
end
function http_post(zurl,zarg)
if #t_zurl <=10 then table.insert(t_zurl, zurl) table.insert(t_zarg, zarg) end
-- if verbose then print("Nb wait: "..#t_zurl) print(node.heap()) end
-- 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:") end
collectgarbage()
-- if verbose then print(node.heap()) end
end

View File

@@ -0,0 +1,148 @@
-- script telnet pour le socat
function telnet_listener(socket)
print("\n 0_rtelnet1.lua zf200621.2309 \n")
-- node, table, tmr, uwrite, tostring =
-- node, table, tmr, uart.write, tostring
print("................telnet_listener")
-- insert, remove, concat, heap, gc =
-- table.insert, table.remove, table.concat, node.heap, collectgarbage
fifo1, fifo1l, fifo2, fifo2l = {}, 0, {}, 0
-- local s -- s is a copy of the TCP socket if and only if sending is in progress
function flushGarbage()
if node.heap() < 13440 then collectgarbage() end
end
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
table.insert(fifo2,table.concat(fifo1))
fifo2l, fifo1, fifo1l = fifo2l + fifo1l, {}, 0
end
rec = table.remove(fifo2,1)..(table.remove(fifo2,1) or '') ..(table.remove(fifo2,1) or '') .. (table.remove(fifo2,1) or '')
fifo2l = fifo2l - #rec
flushGarbage()
if srv_rt:getpeer()~=nil then
s:send(rec)
end
end
local F1_SIZE = 256
function queueLine(str)
while #str > 0 do -- this is because str might be longer than the packet size!
k, l = F1_SIZE - fifo1l, #str
if #fifo1 >= 32 or (k < l and k < 16) then
table.insert(fifo2, table.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
table.insert(fifo1, chunk)
fifo1l = fifo1l + #chunk
end
if not s and socket then
s = socket
sendLine()
else
flushGarbage()
end
end
function receiveLine(s, line)
node.input(line)
end
function disconnect(_,zerr)
node.output(nil)
gpio.write(zLED, gpio.HIGH)
print("................disconnect")
if socket~=nil then
-- if http_post~=nil then http_post(influxdb_url,"energy,memory=srv_rt_no_nil_"..yellow_id.." ram="..node.heap()) end
print("................disconnect 2e", socket, socket:getpeer())
socket:on("connection", nil)
socket:on("reconnection", nil)
socket:on("disconnection", nil)
socket:on("receive", nil)
socket:on("sent", nil)
socket=nil
end
-- fifo1, fifo1l, fifo2, fifo2l, s = nil, nil, nil, nil, nil
print("disconnected... "..zerr..", "..node.heap())
-- if debug_rec~=nil then debug_rec("disconnect, disconnected, "..zerr..", "..node.heap()) end
-- node, table, tmr, uwrite, tostring = nil, nil, nil, nil, nil
-- insert, remove, concat, heap, gc = nil, nil, nil, nil, nil
-- fifo1, fifo1l, fifo2, fifo2l = nil, nil, nil, nil
-- rec = nil
-- s = nil
-- socket = nil
-- flushGarbage = nil
-- sendLine = nil
-- queueLine = nil
-- receiveLine = nil
-- zconnection = nil
-- disconnect = nil
-- -- telnet_listener=nil
fifo1, fifo1l, fifo2, fifo2l = nil, nil, nil, nil
rec = nil
k = nil
l = nil
s = nil
chunk = nil
socket = nil
flushGarbage = nil
sendLine = nil
queueLine = nil
receiveLine = nil
zconnection = nil
disconnect = nil
telnet_listener=nil
srv_rt=nil
-- collectgarbage()
rt_connect()
end
--zzz
function zconnection(s)
print("socket: ",socket)
if socket~=nil then
-- if http_post~=nil then http_post(influxdb_url,"energy,memory=srv_rt_no_nil_"..yellow_id.." ram="..node.heap()) end
print(socket:getpeer())
end
local zstr="zconnection, Oups, on ne devrait jamais passer par là to NodeMCU world."
print(zstr) if debug_rec~=nil then debug_rec(zstr) end
socket=nil
end
socket:on("connection", zconnection)
socket:on("receive", receiveLine)
socket:on("disconnection", disconnect)
socket:on("sent", sendLine)
node.output(queueLine, 0)
-- print(queueLine, 0)
end

View File

@@ -0,0 +1,115 @@
--[[
tests connection reverse telnet commande à faire tourner sur le GATEWAY !
1ere console
pour une liaison directe:
socat TCP-LISTEN:23064,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_tst5_socat.lua zf200621.2330 \n")
function rt_connect()
print("................rt_connect")
collectgarbage()
local zlaps=tmr.now()/1000000-ztime_connect
print("time of retry connect... "..zlaps)
-- if debug_rec~=nil then debug_rec("time of retry connect... "..zlaps..", "..node.heap()) end
if zlaps>1 then
local zstr="trying connect to "..console_host..":"..console_port..", "..node.heap()
-- if debug_rec~=nil then debug_rec(zstr) end
if verbose==verbose then
gpio.write(zLED, gpio.LOW) tmr.delay(10000) gpio.write(zLED, gpio.HIGH)
print(zstr)
end
if http_post~=nil then http_post(influxdb_url,"energy,memory=socat_try_con_"..yellow_id.." ram="..node.heap()) end
ztime_connect=tmr.now()/1000000
srv_rt=nil
srv_rt = net.createConnection(net.TCP, 0)
srv_rt:on("connection", function(sck)
print("................connection")
if debug_rec~=nil then debug_rec("rt_connect, srv_rt:on, connected on, "..node.heap()) end
collectgarbage()
-- if verbose then
gpio.write(zLED, gpio.LOW)
print("connected on "..console_host..":"..console_port..", "..node.heap())
print(node.heap())
-- end
if http_post~=nil then http_post(influxdb_url,"energy,memory=socat_connected_"..yellow_id.." ram="..node.heap()) end
dofile("0_rtelnet1.lua")
telnet_listener(sck)
print("Welcome to NodeMCU world.")
end)
srv_rt:on("reconnection", function(sck)
print(";;;;;;;;;;;;;;;;reconnection")
srv_rt:on("connection", nil)
srv_rt:on("reconnection", nil)
end)
-- srv_rt:on("disconnection", function(sck)
-- print(";;;;;;;;;;;;;;;;disconnection")
-- end)
--
-- srv_rt:on("receive", function(sck)
-- print(";;;;;;;;;;;;;;;;receive")
-- end)
--
-- srv_rt:on("sent", function(sck)
-- print(";;;;;;;;;;;;;;;;sent")
-- end)
srv_rt:connect(console_port,console_host)
else
print("on ne se reconnecte pas vite 1x...")
end
collectgarbage()
end
function rt_launch()
if http_post~=nil then http_post(influxdb_url,"energy,memory=tmr_socat1_"..yellow_id.." ram="..node.heap()) end
if srv_rt~=nil then
-- if http_post~=nil then http_post(influxdb_url,"energy,memory=srv_rt_no_nil_"..yellow_id.." ram="..node.heap()) end
if console_port ~= srv_rt:getpeer() then
rt_connect()
end
else
rt_connect()
end
end
-- tmr_socat1=tmr.create()
-- tmr_socat1:alarm(15*1000, tmr.ALARM_AUTO , rt_launch)
ztime_connect=tmr.now()/1000000-10
rt_launch()
print("Revers telnet server running...\n")

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=15i9nclcC4R4JQXcMzhG9KSDj07QgJhIguNgV_eQx1BI", "doc_id": "15i9nclcC4R4JQXcMzhG9KSDj07QgJhIguNgV_eQx1BI", "email": "christian.zufferey@gmail.com"}

View File

@@ -0,0 +1,192 @@
# Mesure d'énergie d'une installation monophasée
Version pour l'installation solaire qui se trouve sur le toit !
zf200607.1211
Profilage de fuites mémoire sur IoT avec Lua
https://docs.google.com/document/d/1H96RfhmMhTz6i1bq8uWTP3cOSOQD-78dgeGNKpzsJRg/edit?usp=sharing
**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

@@ -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,79 @@
zf200621.2337
srv_rt:on("connection", nil)
=node.heap()
rt_connect()
fifo1, fifo1l, fifo2, fifo2l = nil, nil, nil, nil
rec = nil
k = nil
l = nil
s = nil
chunk = nil
socket = nil
flushGarbage = nil
sendLine = nil
queueLine = nil
receiveLine = nil
zconnection = nil
disconnect = nil
telnet_listener=nil
srv_rt=nil
=node.heap()
=node.heap()
dofile("0_rtelnet1.lua")
=node.heap()
telnet_listener=nil
=node.heap()
srv_rt=nil
=node.heap()
for k,v in ipairs(debug.getregistry()) do print(k,v) end
node.stripdebug(3)
node.compile('0_tst4_socat.lua')
print(srv_rt)
print(srv_rt:getpeer())
srv_rt:close()
print(socket)
print(socket:getpeer())
socket:close()
verbose=true
node.output(nil)
http_post(influxdb_url,"energy,value=test1_"..yellow_id.." val=1") print("toto",node.heap(),#t_zurl)
=srv_rt:getaddr()
tmr_socat1:unregister()
for k,v in pairs(_G) do print(k,v) end
total_allocated, estimated_used = node.egc.meminfo()
print(total_allocated, estimated_used)
print(console_port)
srv_rt = nil collectgarbage()

View File

@@ -0,0 +1,292 @@
# Quelques commandes remote (luatool) à envoyer avec le plugin Atom-IDE-terminal de l'éditeur Atom
# zf200621.2312
Todo à faire pour ce projet !
???
# 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 #
################################
# pour les tests en direct sur la gateway
ssh ubuntu@www.zuzu-test.ml
socat TCP-LISTEN:23064,fork,reuseaddr STDIO
################################
# pour les tests en remote
killall -9 ssh
ssh ubuntu@www.zuzu-test.ml killall -9 socat
ssh ubuntu@www.zuzu-test.ml socat TCP-LISTEN:23064,reuseaddr,fork TCP-LISTEN:23000,reuseaddr,bind=127.0.0.1 &
# SHIFT+CMD+K SHIFT+CMD+K ALT+CMD+F
watch -n 1 'ssh ubuntu@www.zuzu-test.ml netstat -nat |grep 230'
# ALT+CMD+F CTRL+C ALT+CMD+F
export zIP="localhost"
export zport="23000"
ssh -N -L 23000:localhost:23000 ubuntu@www.zuzu-test.ml &
telnet -rN $zIP $zport
=node.heap()
~.
verbose=false
= node.bootreason()
# https://nodemcu.readthedocs.io/en/master/modules/node/#nodebootreason
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 0_get_power.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 -f 0_tst4_socat.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,66 @@
-- Scripts à charger après le boot pour démarrer son projet
function boot()
print("\n boot.lua zf200621.1939 \n")
print("On lance le boot...")
collectgarbage() print(node.heap())
local f
f = "0_http_post.lua" if file.exists(f) then dofile(f) end
collectgarbage() print(node.heap())
local _, boot_reason = node.bootreason()
zarg_boot= "energy,memory=boot_"..yellow_id.." ram="..node.heap().."\n"
zarg_boot=zarg_boot.."energy,value=boot_reason_"..yellow_id.." val="..boot_reason
http_post(influxdb_url,zarg_boot)
-- 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
collectgarbage() print(node.heap())
zpower=0
f="0_get_power.lua" if file.exists(f) then dofile(f) end
collectgarbage() print(node.heap())
f="0_cron.lua" if file.exists(f) then dofile(f) end
collectgarbage() print(node.heap())
verbose = true
print("verbose: ",verbose,"\nle boot est lancé...")
gpio.write(zLED, gpio.HIGH)
f=nil boot=nil
end
-- function debug_rec(zdebug)
-- local sec, usec = rtctime.get() local tm = rtctime.epoch2cal(sec + 2*3600)
-- local ztm = string.format("%04d/%02d/%02d %02d:%02d:%02d", tm["year"], tm["mon"], tm["day"], tm["hour"], tm["min"], tm["sec"])
-- file.open("00_debug.txt", "a+") file.writeline(ztm.."."..usec..", "..zdebug) file.close()
-- end
--
-- function rec_boot()
-- sntp.sync(nil, nil, nil, 1)
-- tmr_rec_boot1=tmr.create()
-- tmr_rec_boot1:alarm(1*1000, tmr.ALARM_AUTO, function()
-- print("beep...")
-- if rtctime.get() > 0 then
-- tmr_rec_boot1:unregister()
-- print("Voilà on à l'heure, on peut enregistrer la raison du boot...")
-- local _, zboot_reason, zboot_detail = node.bootreason()
-- debug_rec("boot reason: "..zboot_reason)
-- tmr_rec_boot1=nil rec_boot=nil
-- collectgarbage() print(node.heap())
-- end
-- end)
-- end
verbose=true
if rec_boot~=nil then rec_boot() end
boot()
collectgarbage() print(node.heap())
--[[
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 dir.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 801 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 792 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 821 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 548 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 914 KiB

View File

@@ -0,0 +1,86 @@
--Script de bootstrap, test au moment du boot qui a été la cause de boot.
-- Si la cause est un power on ou une connexion depuis l'IDE, alors
-- le script repair.lua pendant xx secondes avant de continuer
--Source: https://nodemcu.readthedocs.io/en/master/en/modules/node/#nodebootreason
print("\n init.lua zf200612.1632 \n")
verbose = true
function initz()
function initz_end()
print("initz_end...")
f= "wifi_init.lua" if file.exists(f) then dofile(f) end
f=nil initz=nil second_chance=nil hvbouton=nil initz_end=nil
print(node.heap()) collectgarbage() print(node.heap())
print("initz_end out...")
end
function hvbouton()
gpio.trig(zswitch, "none") zswitch=nil
print("hvbouton...")
print(tmr.now())
if tmr.now() > 5000000 then
file.putcontents("_setup_wifi_", "toto")
print("on a demandé le setup wifi !")
end
initalarme1:unregister() initalarme1=nil second_chance=nil
gpio.write(zLED, gpio.HIGH) zLED=nil
reset_reason="hvbouton"
initz_end()
end
function second_chance()
print("seconde chance...")
zLED=4 -- NodeMCU
--zLED=7 -- SonOff
gpio.write(zLED, gpio.LOW) gpio.mode(zLED, gpio.OUTPUT)
initalarme1=tmr.create()
initalarme1:alarm(10*1000, tmr.ALARM_SINGLE, function()
gpio.write(zLED, gpio.HIGH) zLED=nil
gpio.trig(zswitch, "none") zswitch=nil
reset_reason="seconde_chance"
initz_end()
end)
zswitch=3 --switch flash ou SonOff
gpio.mode(zswitch, gpio.INT, gpio.PULLUP)
gpio.trig(zswitch, "both", hvbouton)
end
_, reset_reason = node.bootreason()
print("reset_reason: ",reset_reason)
if reset_reason == 0 then
print("power on")
second_chance()
elseif reset_reason == 4 then
print("node.restart")
initz_end()
elseif reset_reason == 5 then
print("dsleep wake up")
initz_end()
elseif reset_reason == 6 then
print("external reset")
second_chance()
else
print("autre raison")
second_chance()
end
end
initz()
--[[
zLED=7
gpio.mode(zLED, gpio.OUTPUT)
gpio.write(zLED, gpio.LOW) -- actif !
gpio.write(zLED, gpio.HIGH)
zBTN=3
gpio.mode(zBTN, gpio.INPUT)
print(gpio.read(zBTN))
zRELAY=6
gpio.mode(zRELAY, gpio.OUTPUT)
gpio.write(zRELAY, gpio.HIGH) -- actif !
gpio.write(zRELAY, gpio.LOW)
]]

View File

@@ -0,0 +1,408 @@
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
version = "0.6.8 zf191225.1428"
print("luatool.py ver " + version)
#Améliorations
# Pour voir les améliorations il faut 'chercher' les zzz
#
# ESP8266 luatool
# Author e-mail: 4ref0nt@gmail.com
# Site: http://esp8266.ru
# Contributions from: https://github.com/sej7278
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# Street, Fifth Floor, Boston, MA 02110-1301 USA.
import sys
import serial
from time import sleep
import socket
import argparse
from os.path import basename
tqdm_installed = True
try:
from tqdm import tqdm
except ImportError, e:
if e.message == 'No module named tqdm':
tqdm_installed = False
else:
raise
class TransportError(Exception):
"""Custom exception to represent errors with a transport
"""
def __init__(self, message):
self.message = message
def __str__(self):
return self.message
class AbstractTransport:
def __init__(self):
raise NotImplementedError('abstract transports cannot be instantiated.')
def close(self):
raise NotImplementedError('Function not implemented')
def read(self, length):
raise NotImplementedError('Function not implemented')
def writeln(self, data, check=1):
raise NotImplementedError('Function not implemented')
def writer(self, data):
##zzz191124 enlève la fin de ligne afin de ne pas perturber la vérification finale
data = data.rstrip('\r\n')
self.writeln("file.writeline([==[" + data + "]==])\r")
def performcheck(self, expected):
line = ''
char = ''
i = -1
while char != chr(62): # '>'
char = self.read(1)
if char == '':
raise Exception('No proper answer from MCU')
if char == chr(13) or char == chr(10): # LF or CR
if line != '':
#zzz191124 line = line.strip()
# zzz191021 Affiche ce que l'on a reçu du NodeMCU
if args.verbose:
print("\n\nzread0957: {" + line + "\n}\n")
if line+'\r' == expected and not args.bar:
sys.stdout.write(" -> ok")
elif line+'\r' != expected:
if line[:4] == "lua:":
sys.stdout.write("\r\n\r\nLua ERROR: %s" % line)
raise Exception('ERROR from Lua interpreter\r\n\r\n')
else:
expected = expected.split("\r")[0]
sys.stdout.write("\r\n\r\nERROR")
sys.stdout.write("\r\n send string : '%s'" % expected)
sys.stdout.write("\r\n expected echo : '%s'" % expected)
sys.stdout.write("\r\n but got answer : '%s'" % line)
sys.stdout.write("\r\n\r\n")
raise Exception('Error sending data to MCU\r\n\r\n')
line = ''
else:
line += char
if char == chr(62) and expected[i] == char:
char = ''
i += 1
class SerialTransport(AbstractTransport):
def __init__(self, port, baud, delay):
self.port = port
self.baud = baud
self.serial = None
self.delay = delay
try:
self.serial = serial.Serial(port, baud)
except serial.SerialException as e:
raise TransportError(e.strerror)
self.serial.timeout = 3
self.serial.interCharTimeout = 3
# zzz191021 juste après l'ouverture du port série, on attend le caractère '>'
line = ''
char = ''
i = -1
while char != chr(62): # '>'
char = self.read(1)
if char == '':
raise Exception('No proper answer from MCU')
line += char
i += 1
if args.verbose:
print("line: ." + line + ".")
def writeln(self, data, check=1):
# zzz191020 on fait une petite pause avant l'envoi de chaque ligne
sleep(self.delay)
if self.serial.inWaiting() > 0:
self.serial.flushInput()
if len(data) > 0 and not args.bar:
sys.stdout.write("\r\n->")
sys.stdout.write(data.split("\r")[0])
##zzz191124 attend encore un petit peu avant d'envoyer
sleep(self.delay)
self.serial.write(data)
sleep(self.delay)
# zzz191021 Affiche ce que l'on a envoyé au NodeMCU
if args.verbose:
print("\n\nzwrite0952: {" + data + "\n}\n")
if check > 0:
self.performcheck(data)
elif not args.bar:
sys.stdout.write(" -> send without check")
def read(self, length):
return self.serial.read(length)
def close(self):
self.serial.flush()
self.serial.close()
class TcpSocketTransport(AbstractTransport):
def __init__(self, host, port):
self.host = host
self.port = port
self.socket = None
try:
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error as e:
raise TransportError(e.strerror)
try:
self.socket.connect((host, port))
except socket.error as e:
raise TransportError(e.strerror)
# read intro from telnet server (see telnet_srv.lua)
self.socket.recv(50)
def writeln(self, data, check=1):
if len(data) > 0 and not args.bar:
sys.stdout.write("\r\n->")
sys.stdout.write(data.split("\r")[0])
self.socket.sendall(data)
if check > 0:
self.performcheck(data)
elif not args.bar:
sys.stdout.write(" -> send without check")
def read(self, length):
return self.socket.recv(length)
def close(self):
self.socket.close()
def decidetransport(cliargs):
if cliargs.ip:
data = cliargs.ip.split(':')
host = data[0]
if len(data) == 2:
port = int(data[1])
else:
port = 23
return TcpSocketTransport(host, port)
else:
return SerialTransport(cliargs.port, cliargs.baud, cliargs.delay)
if __name__ == '__main__':
# parse arguments or use defaults
parser = argparse.ArgumentParser(description='ESP8266 Lua script uploader.')
parser.add_argument('--bar', action='store_true', help='Show a progress bar for uploads instead of printing each line')
parser.add_argument('--delay', default=0.025, help='Delay in seconds between each write, default 0.03 sec.', type=float)
parser.add_argument('--delete', default=None, help='Delete a lua/lc file from device.')
parser.add_argument('--ip', default=None, help='Connect via telnet server (--ip IP[:port])')
parser.add_argument('--zrestart', action='store_true', help='Restart the NodeMCU.')
parser.add_argument('-a', '--append', action='store_true', help='Append source file to destination file.')
parser.add_argument('-b', '--baud', default=115200, help='Baudrate, default 115200')
parser.add_argument('-c', '--compile', action='store_true', help='Compile lua to lc after upload')
parser.add_argument('-d', '--dofile', action='store_true', help='Run the Lua script after upload')
parser.add_argument('-e', '--echo', action='store_true', help='Echo output of MCU until script is terminated.')
parser.add_argument('-f', '--src', default='main.lua', help='Source file on computer, default main.lua')
parser.add_argument('-i', '--id', action='store_true', help='Query the modules chip id.')
parser.add_argument('-l', '--list', action='store_true', help='List files on device')
parser.add_argument('-p', '--port', default='/dev/ttyUSB0', help='Device name, default /dev/ttyUSB0')
parser.add_argument('-r', '--restart', action='store_true', help='Restart MCU after upload')
parser.add_argument('-t', '--dest', default=None, help='Destination file on MCU, default to source file name')
parser.add_argument('-v', '--verbose', action='store_true', help="Show progress messages.")
parser.add_argument('-w', '--wipe', action='store_true', help='Delete all lua/lc files on device.')
args = parser.parse_args()
transport = decidetransport(args)
if args.bar and not tqdm_installed:
sys.stdout.write("You must install the tqdm library to use the bar feature\n")
sys.stdout.write("To install, at the prompt type: \"pip install tqdm\"\n")
sys.exit(0)
if args.list:
# zzz191020 Amélioré la sortie du listing des fichiers
#transport.writeln("print('\\n-----');local l = file.list();for k,v in pairs(l) do print(k..', size:'..v)end;print('-----\\n')\r", 0)
# zzz191225 Amélioré encore la sortie du listing des fichiers (sort file)
transport.writeln("zdir={};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);print('\\n-----');for i=1, #zdir do print(zdir[i]) end;print('-----\\n');zdir=nil;pfile=nil;k=nil;v=nil;i=nil\r", 0)
while True:
char = transport.read(1)
if char == '' or char == chr(62): # '' or '>'
break
sys.stdout.write(char)
sys.exit(0)
if args.id:
transport.writeln("=node.chipid()\r", 0)
id=""
while True:
char = transport.read(1)
if char == '' or char == chr(62):
break
if char.isdigit():
id += char
print("\n"+id)
sys.exit(0)
# zzz191020 Ajouté la fonction restart seule
if args.zrestart:
transport.writeln("node.restart()\r")
sys.exit(0)
if args.wipe:
transport.writeln("local l = file.list();for k,v in pairs(l) do print(k)end\r", 0)
file_list = []
fn = ""
while True:
char = transport.read(1)
if char == '' or char == chr(62):
break
if char not in ['\r', '\n']:
fn += char
else:
if fn:
file_list.append(fn.strip())
fn = ''
for fn in file_list[1:]: # first line is the list command sent to device
if args.verbose:
sys.stderr.write("Delete file {} from device.\r\n".format(fn))
transport.writeln("file.remove(\"" + fn + "\")\r")
sys.exit(0)
if args.delete:
transport.writeln("file.remove(\"" + args.delete + "\")\r")
sys.exit(0)
if args.dest is None:
args.dest = basename(args.src)
# zzz191020 Affiche le fichier à envoyer
print("File: " + args.src)
# open source file for reading
try:
try:
f = open(args.src, "rt")
except:
import os
base_dir = os.path.dirname(os.path.realpath(__file__))
f = open(os.path.join(base_dir, args.src), "rt")
os.chdir(base_dir)
except:
sys.stderr.write("Could not open input file \"%s\"\n" % args.src)
sys.exit(1)
# Verify the selected file will not exceed the size of the serial buffer.
# The size of the buffer is 256. This script does not accept files with
# lines longer than 230 characters to have some room for command overhead.
num_lines = 0
for ln in f:
if len(ln) > 230:
sys.stderr.write("File \"%s\" contains a line with more than 240 "
"characters. This exceeds the size of the serial buffer.\n"
% args.src)
f.close()
sys.exit(1)
num_lines += 1
# Go back to the beginning of the file after verifying it has the correct
# line length
f.seek(0)
# set serial timeout
if args.verbose:
sys.stderr.write("Upload starting\r\n")
# remove existing file on device
if args.append==False:
if args.verbose:
sys.stderr.write("Stage 1. Deleting old file from flash memory")
transport.writeln("file.open(\"" + args.dest + "\", \"w\")\r")
transport.writeln("file.close()\r")
transport.writeln("file.remove(\"" + args.dest + "\")\r")
else:
if args.verbose:
sys.stderr.write("[SKIPPED] Stage 1. Deleting old file from flash memory [SKIPPED]")
# read source file line by line and write to device
if args.verbose:
sys.stderr.write("\r\nStage 2. Creating file in flash memory and write first line")
if args.append:
transport.writeln("file.open(\"" + args.dest + "\", \"a+\")\r")
else:
transport.writeln("file.open(\"" + args.dest + "\", \"w+\")\r")
line = f.readline()
if args.verbose:
sys.stderr.write("\r\nStage 3. Start writing data to flash memory...")
if args.bar:
for i in tqdm(range(0, num_lines)):
#zzz191124 transport.writer(line.strip())
transport.writer(line)
line = f.readline()
else:
while line != '':
#zzz191124 transport.writer(line.strip())
transport.writer(line)
line = f.readline()
# close both files
f.close()
if args.verbose:
sys.stderr.write("\r\nStage 4. Flush data and closing file")
transport.writeln("file.flush()\r")
transport.writeln("file.close()\r")
# compile?
if args.compile:
if args.verbose:
sys.stderr.write("\r\nStage 5. Compiling")
transport.writeln("node.compile(\"" + args.dest + "\")\r")
transport.writeln("file.remove(\"" + args.dest + "\")\r")
# restart or dofile
if args.restart:
transport.writeln("node.restart()\r")
if args.dofile: # never exec if restart=1
transport.writeln("dofile(\"" + args.dest + "\")\r", 0)
if args.echo:
if args.verbose:
sys.stderr.write("\r\nEchoing MCU output, press Ctrl-C to exit")
while True:
sys.stdout.write(transport.read(1))
# close serial port
transport.close()
# flush screen
sys.stdout.flush()
sys.stderr.flush()
if not args.bar:
sys.stderr.write("\r\n--->>> All done <<<---\r\n")

View File

@@ -0,0 +1,13 @@
-- Petit script pour faire office de crontab pour les
--mesures
print("\n 0_cron.lua zf190917.0033 \n")
f= "flash_led_xfois.lua" if file.exists(f) then dofile(f) end
flash_led_xfois()
xfois =2
cron1=tmr.create()
cron1:alarm(10*1000, tmr.ALARM_AUTO, function()
blink_LED ()
send_data()
end)

View File

@@ -0,0 +1,40 @@
-- Scripts qui permet d'enregistrer la raison du boot dans la flash
-- Problématique:
-- Afin de pouvoir enregistrer l'heure du boot dans la FLASH il faut
-- en premier récupérer l'heure sur Internet et après seulement on peut
-- faire l'enregistrement dans la FLASH
function rec_boot()
print("\n 0_rec_boot.lua zf200616.1400 \n")
local tmr_rec_boot1=tmr.create()
tmr_rec_boot1:alarm(1*1000, tmr.ALARM_AUTO, function()
if verbose then print("tmr_rec_boot1........................") end
if verbose then gpio.write(zLED, gpio.LOW) tmr.delay(10000) gpio.write(zLED, gpio.HIGH) end
if verbose then print(rtctime.get()) end
if verbose then print(ztime_format(rtctime.get()+3600)) end
if rtctime.get() > 0 then
tmr_rec_boot1:unregister()
print("Voilà on à l'heure, on peut enregistrer la raison du boot...")
local _, zboot_reason, zboot_detail = node.bootreason()
debug_rec("boot reason: "..zboot_reason)
tmr_rec_boot1=nil rec_boot=nil
collectgarbage() print(node.heap())
end
if verbose then print("End tmr_rec_boot1:") end
collectgarbage()
if verbose then print(node.heap()) end
end)
end
rec_boot()
--[[
verbose = true
verbose = false
]]

View File

@@ -0,0 +1,27 @@
-- Petit script pour envoyer les valeurs sur un serveur WEB (InfluxDB)
-- via un http GET
print("\n 0_send_data.lua zf190924.1043 \n")
function send_data()
if verbose then print("send_data: ") end
zarg="energy,compteur=2 puissance="..zpower/1000
if verbose then print("zarg: "..zarg) end
http.post(influxdb_url, 'Content-Type: application/x-www-form-urlencoded\r\n', zarg, function(code, data)
-- print("toto")
if (code < 0) then
print("HTTP request failed")
print("zuzu", code, data)
else
if verbose then print(code, data) end
end
-- print("tutu")
end)
-- print("titi")
end
--[[
zpower=450
send_data()
]]

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,19 @@
-- Petit script pour configurer les choses secrètes que l'on n'aimerait
-- pas être exportées sur Internet (github)
-- donc on ne met PAS des secrets dans le code !
-- faut le mettre ailleurs que dans le dépôt !
-- il faut le renommer en 'secrets_energy.lua' et sera exécuté
-- par 'boot.lua' au moment du boot
function secrets()
print("\n secrets_energy.lua zf190916.1458 \n")
cli_ssid="xxx"
cli_pwd="xxx"
influxdb_url="http://xxx.yyy.zzz:8086/write?db=xxx&u=admin&p=xxx"
print("influxdb_url: "..influxdb_url)
end
secrets()
secrets=nil

View File

@@ -0,0 +1,55 @@
# Quelques commandes remote (luatool) à envoyer avec le plugin Atom-IDE-terminal de l'éditeur Atom
# zf191026.0913
# 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.135"
# ouvrir et fermer (ALT+n+.) une session telnet sur le NodeMCU avec l'adresse zIP)
telnet -rN $zIP
~.
node.restart()
=node.heap()
# commandes lua pour ce projet
verbose=true
verbose=false
#commandes luatool pour ce projet
./luatool.py --ip $zIP -f 0_get_data.lua
./luatool.py --ip $zIP -f 0_send_data.lua
./luatool.py --ip $zIP -f cat.lua
~.
./luatool.py --ip $zIP -f head.lua
telnet -rN $zIP
dofile("head.lua")
zhead("telnet_srv2.lua")
./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 -i
./luatool.py --ip $zIP -l
./luatool.py --ip $zIP -f toto.lua -d
./luatool.py --ip $zIP --delete toto.lua

View File

@@ -0,0 +1,39 @@
<!DOCTYPE html>
<!-- ATTENTION, la longueur des lignes DOIT être <128 ! -->
<html lang="fr" dir="ltr">
<head>
<meta charset='utf-8' name='viewport' content='width=device-width, initial-scale=1.0'>
<title>API SonOff</title>
</head>
<body>
<h1>API SonOff zf200118.1812</h1>
<a href="/">Home...</a><br><br>
<%
if _GET.LED == "on" then
gpio.write(zLED, gpio.LOW) gpio.mode(zLED, gpio.OUTPUT)
zout("LED=".._GET.LED.."<br>")
zout('<a href="api_sonoff.html?LED=off"> Off</a><br>')
end
if _GET.LED == "off" then
gpio.write(zLED, gpio.HIGH) gpio.mode(zLED, gpio.OUTPUT)
zout("LED=".._GET.LED.."<br>")
zout('<a href="api_sonoff.html?LED=on"> On</a>')
end
%>
<%
if _GET.RELAY == "on" then
gpio.mode(zRELAY, gpio.OUTPUT) gpio.write(zRELAY, gpio.HIGH)
zout("RELAY=".._GET.RELAY.."<br>")
zout('<a href="api_sonoff.html?RELAY=off"> Off</a><br>')
end
if _GET.RELAY == "off" then
gpio.mode(zRELAY, gpio.OUTPUT) gpio.write(zRELAY, gpio.LOW)
zout("RELAY=".._GET.RELAY.."<br>")
zout('<a href="api_sonoff.html?RELAY=on"> On</a>')
end
%>
</body>
</html>

View File

@@ -0,0 +1,15 @@
-- Scripts à charger après le boot pour démarrer le core system
print("\n boot.lua zf190916.2359 \n")
-- charge ses propres secrets
f= "secrets_energy.lua" if file.exists(f) then dofile(f) end
--f= "led_rgb.lua" if file.exists(f) then dofile(f) end
--f= "wifi_ap_start.lua" if file.exists(f) then dofile(f) end
f= "wifi_ap_stop.lua" if file.exists(f) then dofile(f) end
f= "wifi_cli_conf.lua" if file.exists(f) then dofile(f) end
f= "wifi_cli_start.lua" if file.exists(f) then dofile(f) end
f= "telnet_srv2.lua" if file.exists(f) then dofile(f) end
f= "web_ide2.lua" if file.exists(f) then dofile(f) end
f= "web_srv2.lua" if file.exists(f) then dofile(f) end

View File

@@ -0,0 +1,22 @@
-- Scripts à charger après le boot pour démarrer son appli
print("\n boot2.lua zf190917.0030 \n")
second_chance=nil
function heartbeat()
f= "flash_led_xfois.lua" if file.exists(f) then dofile(f) end
flash_led_xfois()
boottimer1=tmr.create()
boottimer1:alarm(1*1000, tmr.ALARM_AUTO, function()
xfois =2
blink_LED ()
end)
end
f= "0_get_data.lua" if file.exists(f) then dofile(f) end
f= "0_send_data.lua" if file.exists(f) then dofile(f) end
f= "0_cron.lua" if file.exists(f) then dofile(f) end
f=nil
heartbeat=nil
--heartbeat()

View File

@@ -0,0 +1,15 @@
-- fonction dir() pour afficher les fichiers dans la flash
print("\n dir.lua zf180826.1019 \n")
function dir()
print("\n-------------------------------")
l=file.list() i=0
for k,v in pairs(l) do
i=i+v
print(k..string.rep(" ",19-string.len(k)).." : "..v.." bytes")
end
print("-------------------------------")
print('\nUsed: '..i..' bytes\nusage: dofile("file.lua")\n')
end
dir()

View File

@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="fr" dir="ltr">
<head>
<meta charset='utf-8' name='viewport' content='width=device-width, initial-scale=1.0'>
<title>Affichage des températures</title>
</head>
<body>
<h1>Affichage des températures 190727.1349</h1>
<br>
Les températures mesurées sont:<br>
<%
if (ztemp1 ~= nil) then
zout("<br>Température intérieure chambre à coucher "..ztemp1.."°C")
end
if (ztemp2 ~= nil) then
zout("<br>Température extérieure sud (nodemcu 29) "..ztemp2.."°C")
end
if (ztemp3 ~= nil) then
zout("<br>Température extérieure nord (nodemcu 30) "..ztemp3.."°C")
end
zout("<br><br>RAM: "..node.heap().."<br>")
%>
</body>
</html>

View File

@@ -0,0 +1,23 @@
<!DOCTYPE html>
<html lang="fr" dir="ltr">
<head>
<meta charset='utf-8' name='viewport' content='width=device-width, initial-scale=1.0'>
<title>Affichage de la température et humidité</title>
</head>
<body>
<h1>Affichage de la température et humidité 200118.1800</h1>
<a href="/">Home...</a><br>
<%
zout("<h1>"..node_id.."&nbsp;&nbsp;&nbsp; 200112.1919 </h1>")
%>
<br>
<%
zout("Température: "..readTemp().." °C<br>")
zout("Humidité: "..readHumi().." %<br>")
zout("<br><br>RAM: "..node.heap().."<br>")
%>
</body>
</html>

View File

@@ -0,0 +1,52 @@
t = require("ds18b20")
pin = 3 -- gpio0 = 3, gpio2 = 4
local function readout(temp)
if t.sens then
print("Total number of DS18B20 sensors: ".. #t.sens)
for i, s in ipairs(t.sens) do
print(string.format(" sensor #%d address: %s%s", i, ('%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X'):format(s:byte(1,8)), s:byte(9) == 1 and " (parasite)" or ""))
end
end
for addr, temp in pairs(temp) do
print(string.format("Sensor %s: %s °C", ('%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X'):format(addr:byte(1,8)), temp))
end
-- Module can be released when it is no longer needed
--t = nil
--package.loaded["ds18b20"]=nil
end
t:enable_debug()
file.remove("ds18b20_save.lc") -- remove saved addresses
print("=============================================", node.heap())
print("first call, no addresses in flash, search is performed")
t:read_temp(readout, pin, t.C)
tmr.create():alarm(2000, tmr.ALARM_SINGLE, function()
print("=============================================", node.heap())
print("second readout, no new search, found addresses are used")
t:read_temp(readout, pin)
tmr.create():alarm(2000, tmr.ALARM_SINGLE, function()
print("=============================================", node.heap())
print("force search again")
t:read_temp(readout, pin, nil, true)
tmr.create():alarm(2000, tmr.ALARM_SINGLE, function()
print("=============================================", node.heap())
print("save search results")
t:read_temp(readout, pin, nil, false, true)
tmr.create():alarm(2000, tmr.ALARM_SINGLE, function()
print("=============================================", node.heap())
print("use saved addresses")
t.sens={}
t:read_temp(readout, pin)
end)
end)
end)
end)

View File

@@ -0,0 +1,35 @@
t = require('ds18b20')
port = 80
pin = 3 -- gpio0 = 3, gpio2 = 4
gconn = {} -- global variable for connection
function readout(temp)
local resp = "HTTP/1.1 200 OK\nContent-Type: text/html\nRefresh: 5\n\n" ..
"<!DOCTYPE HTML>" ..
"<html><body>" ..
"<b>ESP8266</b></br>"
for addr, temp in pairs(temp) do
resp = resp .. string.format("Sensor %s: %s &#8451</br>", ('%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X '):format(addr:byte(1,8)), temp)
end
resp = resp ..
"Node ChipID: " .. node.chipid() .. "<br>" ..
"Node MAC: " .. wifi.sta.getmac() .. "<br>" ..
"Node Heap: " .. node.heap() .. "<br>" ..
"Timer Ticks: " .. tmr.now() .. "<br>" ..
"</html></body>"
gconn:send(resp)
gconn:on("sent",function(conn) conn:close() end)
end
srv=net.createServer(net.TCP)
srv:listen(port,
function(conn)
gconn = conn
-- t:read_temp(readout) -- default pin value is 3
t:read_temp(readout, pin)
end
)

View File

@@ -0,0 +1,223 @@
--------------------------------------------------------------------------------
-- DS18B20 one wire module for NODEMCU
-- NODEMCU TEAM
-- LICENCE: http://opensource.org/licenses/MIT
-- @voborsky, @devsaurus, TerryE 26 Mar 2017
----------------------------------------------------------------------------------------------------------------------------------------------------------------
local modname = ...
-- Used modules and functions
local table, string, ow, tmr, print, type, tostring, pcall, ipairs =
table, string, ow, tmr, print, type, tostring, pcall, ipairs
-- Local functions
local ow_setup, ow_search, ow_select, ow_read, ow_read_bytes, ow_write, ow_crc8, ow_reset, ow_reset_search, ow_skip, ow_depower =
ow.setup, ow.search, ow.select, ow.read, ow.read_bytes, ow.write, ow.crc8, ow.reset, ow.reset_search, ow.skip, ow.depower
local node_task_post, node_task_LOW_PRIORITY = node.task.post, node.task.LOW_PRIORITY
local string_char, string_dump = string.char, string.dump
local now, tmr_create, tmr_ALARM_SINGLE = tmr.now, tmr.create, tmr.ALARM_SINGLE
local table_sort, table_concat = table.sort, table.concat
local math_floor = math.floor
local file_open = file.open
table, string, tmr, ow = nil, nil, nil, nil
local DS18B20FAMILY = 0x28
local DS1920FAMILY = 0x10 -- and DS18S20 series
local CONVERT_T = 0x44
local READ_SCRATCHPAD = 0xBE
local READ_POWERSUPPLY= 0xB4
local MODE = 1
local pin, cb, unit = 3
local status = {}
local debugPrint = function() return end
--------------------------------------------------------------------------------
-- Implementation
--------------------------------------------------------------------------------
local function enable_debug()
debugPrint = function (...) print(now(),' ', ...) end
end
local function to_string(addr, esc)
if type(addr) == 'string' and #addr == 8 then
return ( esc == true and
'"\\%u\\%u\\%u\\%u\\%u\\%u\\%u\\%u"' or
'%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X '):format(addr:byte(1,8))
else
return tostring(addr)
end
end
local function readout(self)
local next = false
local sens = self.sens
local temp = self.temp
for i, s in ipairs(sens) do
if status[i] == 1 then
ow_reset(pin)
local addr = s:sub(1,8)
ow_select(pin, addr) -- select the sensor
ow_write(pin, READ_SCRATCHPAD, MODE)
data = ow_read_bytes(pin, 9)
local t=(data:byte(1)+data:byte(2)*256)
-- t is actually signed so process the sign bit and adjust for fractional bits
-- the DS18B20 family has 4 fractional bits and the DS18S20s, 1 fractional bit
t = ((t <= 32767) and t or t - 65536) *
((addr:byte(1) == DS18B20FAMILY) and 625 or 5000)
if 1/2 == 0 then
-- integer version
if unit == 'F' then
t = (t * 18)/10 + 320000
elseif unit == 'K' then
t = t + 2731500
end
local sgn = t<0 and -1 or 1
local tA = sgn*t
local tH=tA/10000
local tL=(tA%10000)/1000 + ((tA%1000)/100 >= 5 and 1 or 0)
if tH and (t~=850000) then
temp[addr]=(sgn<0 and "-" or "")..tH.."."..tL
debugPrint(to_string(addr),(sgn<0 and "-" or "")..tH.."."..tL)
status[i] = 2
end
-- end integer version
else
-- float version
if t and (math_floor(t/10000)~=85) then
t = t / 10000
if unit == 'F' then
t = t * 18/10 + 32
elseif unit == 'K' then
t = t + 27315/100
end
self.temp[addr]=t
debugPrint(to_string(addr), t)
status[i] = 2
end
-- end float version
end
end
next = next or status[i] == 0
end
if next then
node_task_post(node_task_LOW_PRIORITY, function() return conversion(self) end)
else
--sens = {}
if cb then
node_task_post(node_task_LOW_PRIORITY, function() return cb(temp) end)
end
end
end
local function conversion(self)
local sens = self.sens
local powered_only = true
for _, s in ipairs(sens) do powered_only = powered_only and s:byte(9) ~= 1 end
if powered_only then
debugPrint("starting conversion: all sensors")
ow_reset(pin)
ow_skip(pin) -- select the sensor
ow_write(pin, CONVERT_T, MODE) -- and start conversion
for i, s in ipairs(sens) do status[i] = 1 end
else
for i, s in ipairs(sens) do
if status[i] == 0 then
local addr, parasite = s:sub(1,8), s:byte(9)
debugPrint("starting conversion:", to_string(addr), parasite == 1 and "parasite" or " ")
ow_reset(pin)
ow_select(pin, addr) -- select the sensor
ow_write(pin, CONVERT_T, MODE) -- and start conversion
status[i] = 1
if parasite == 1 then break end -- parasite sensor blocks bus during conversion
end
end
end
tmr_create():alarm(750, tmr_ALARM_SINGLE, function() return readout(self) end)
end
local function _search(self, lcb, lpin, search, save)
self.temp = {}
if search then self.sens = {}; status = {} end
local temp = self.temp
local sens = self.sens
pin = lpin or pin
local addr
if not search and #sens == 0 then
-- load addreses if available
debugPrint ("geting addreses from flash")
local s,check,a = pcall(dofile, "ds18b20_save.lc")
if s and check == "ds18b20" then
for i = 1, #a do sens[i] = a[i] end
end
debugPrint (#sens, "addreses found")
end
ow_setup(pin)
if search or #sens == 0 then
ow_reset_search(pin)
-- ow_target_search(pin,0x28)
-- search the first device
addr = ow_search(pin)
else
for i, s in ipairs(sens) do status[i] = 0 end
end
local function cycle()
debugPrint("cycle")
if addr then
local crc=ow_crc8(addr:sub(1,7))
if (crc==addr:byte(8)) and ((addr:byte(1)==DS1920FAMILY) or (addr:byte(1)==DS18B20FAMILY)) then
ow_reset(pin)
ow_select(pin, addr)
ow_write(pin, READ_POWERSUPPLY, MODE)
local parasite = (ow_read(pin)==0 and 1 or 0)
sens[#sens+1]= addr..string_char(parasite) -- {addr=addr, parasite=parasite, status=0}
debugPrint("contact: ", to_string(addr), parasite == 1 and "parasite" or " ")
end
addr = ow_search(pin)
node_task_post(node_task_LOW_PRIORITY, cycle)
else
ow_depower(pin)
-- place powered sensors first
table_sort(sens, function(a, b) return a:byte(9)<b:byte(9) end) -- parasite
-- save sensor addreses
if save then
debugPrint ("saving addreses to flash")
local addr_list = {}
for i =1, #sens do
local s = sens[i]
addr_list[i] = to_string(s:sub(1,8), true)..('.."\\%u"'):format(s:byte(9))
end
local save_statement = 'return "ds18b20", {' .. table_concat(addr_list, ',') .. '}'
debugPrint (save_statement)
local save_file = file_open("ds18b20_save.lc","w")
save_file:write(string_dump(loadstring(save_statement)))
save_file:close()
end
-- end save sensor addreses
if lcb then node_task_post(node_task_LOW_PRIORITY, lcb) end
end
end
cycle()
end
local function read_temp(self, lcb, lpin, lunit, force_search, save_search)
cb, unit = lcb, lunit or unit
_search(self, function() return conversion(self) end, lpin, force_search, save_search)
end
-- Set module name as parameter of require and return module table
local M = {
sens = {},
temp = {},
C = 'C', F = 'F', K = 'K',
read_temp = read_temp, enable_debug = enable_debug
}
_G[modname or 'ds18b20'] = M
return M

View File

@@ -0,0 +1,39 @@
-- programme pour faire clignoter x fois une LED avec un rapport on/off
function flash_led_xfois()
print("\n flash_led_xfois.lua zf190601.1618 \n")
--zLED=0 --NodeMCU
zLED=4 --EPS-M3
zTm_On_LED = 50 --> en ms
zTm_Off_LED = 100 --> en ms
nbfois = 0
gpio.write(zLED, gpio.HIGH)
gpio.mode(zLED, gpio.OUTPUT)
ztmr_Flash_LED = tmr.create()
function blink_LED ()
if nbfois >= xfois then
-- print(nbfois)
nbfois = 0
else
if gpio.read(zLED)==gpio.HIGH then
gpio.write(zLED, gpio.LOW)
-- tmr.alarm(ztmr_Flash_LED, zTm_Off_LED, tmr.ALARM_SINGLE, blink_LED)
ztmr_Flash_LED:alarm(zTm_Off_LED, tmr.ALARM_SINGLE, blink_LED)
else
gpio.write(zLED, gpio.HIGH)
nbfois = nbfois+1
-- tmr.alarm(ztmr_Flash_LED, zTm_On_LED, tmr.ALARM_SINGLE, blink_LED)
ztmr_Flash_LED:alarm(zTm_On_LED, tmr.ALARM_SINGLE, blink_LED)
end
end
end
-- xfois =2
-- blink_LED ()
end

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 zf192026.0942 \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

View File

@@ -0,0 +1,63 @@
--Script de bootstrap, test au moment du boot qui a été la cause de boot.
-- Si la cause est un power on ou une connexion depuis l'IDE, alors
-- le script repair.lua pendant xx secondes avant de continuer
--Source: https://nodemcu.readthedocs.io/en/master/en/modules/node/#nodebootreason
print("\n init.lua zf190917.0001 \n")
zswitch=3 --switch flash
gpio.mode(zswitch, gpio.INT, gpio.PULLUP)
function hvbouton()
gpio.trig(zswitch, "none")
initalarme:unregister() initalarme2:unregister()
f= "boot.lua" if file.exists(f) then dofile(f) end
f= "boot2.lua" if file.exists(f) then dofile(f) end
end
gpio.trig(zswitch, "both", hvbouton)
function second_chance()
print("seconde chance...")
f= "repair.lua" if file.exists(f) then dofile(f) end
initalarme=tmr.create()
initalarme:alarm(4*1000, tmr.ALARM_SINGLE, function()
f= "boot.lua" if file.exists(f) then dofile(f) end
end)
initalarme2=tmr.create()
initalarme2:alarm(30*1000, tmr.ALARM_SINGLE, function()
gpio.trig(zswitch)
hvbouton=nil
zswitch=nil
reset_reason=nil
f= "boot2.lua" if file.exists(f) then dofile(f) end
end)
end
_, reset_reason = node.bootreason()
print("reset_reason:",reset_reason)
if reset_reason == 0 then
print("power on")
second_chance()
elseif reset_reason == 4 then
print("node.restart")
gpio.trig(zswitch)
hvbouton=nil
second_chance=nil
zswitch=nil
reset_reason=nil
f= "boot.lua" if file.exists(f) then dofile(f) end
f= "boot2.lua" if file.exists(f) then dofile(f) end
elseif reset_reason == 5 then
print("dsleep wake up")
f= "boot.lua" if file.exists(f) then dofile(f) end
f= "boot2.lua" if file.exists(f) then dofile(f) end
elseif reset_reason == 6 then
print("external reset")
second_chance()
else
print("autre raison")
second_chance()
end

View File

@@ -0,0 +1,398 @@
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
version = "0.6.5 zf191021.1558"
print("luatool.py ver " + version)
#Améliorations
# Pour voir les améliorations il faut 'chercher' les zzz
#
# ESP8266 luatool
# Author e-mail: 4ref0nt@gmail.com
# Site: http://esp8266.ru
# Contributions from: https://github.com/sej7278
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# Street, Fifth Floor, Boston, MA 02110-1301 USA.
import sys
import serial
from time import sleep
import socket
import argparse
from os.path import basename
tqdm_installed = True
try:
from tqdm import tqdm
except ImportError, e:
if e.message == 'No module named tqdm':
tqdm_installed = False
else:
raise
class TransportError(Exception):
"""Custom exception to represent errors with a transport
"""
def __init__(self, message):
self.message = message
def __str__(self):
return self.message
class AbstractTransport:
def __init__(self):
raise NotImplementedError('abstract transports cannot be instantiated.')
def close(self):
raise NotImplementedError('Function not implemented')
def read(self, length):
raise NotImplementedError('Function not implemented')
def writeln(self, data, check=1):
raise NotImplementedError('Function not implemented')
def writer(self, data):
self.writeln("file.writeline([==[" + data + "]==])\r")
def performcheck(self, expected):
line = ''
char = ''
i = -1
while char != chr(62): # '>'
char = self.read(1)
if char == '':
raise Exception('No proper answer from MCU')
if char == chr(13) or char == chr(10): # LF or CR
if line != '':
line = line.strip()
# zzz191021 Affiche ce que l'on a reçu du NodeMCU
if args.verbose:
print("\n\nzread0957: {" + line + "\n}\n")
if line+'\r' == expected and not args.bar:
sys.stdout.write(" -> ok")
elif line+'\r' != expected:
if line[:4] == "lua:":
sys.stdout.write("\r\n\r\nLua ERROR: %s" % line)
raise Exception('ERROR from Lua interpreter\r\n\r\n')
else:
expected = expected.split("\r")[0]
sys.stdout.write("\r\n\r\nERROR")
sys.stdout.write("\r\n send string : '%s'" % expected)
sys.stdout.write("\r\n expected echo : '%s'" % expected)
sys.stdout.write("\r\n but got answer : '%s'" % line)
sys.stdout.write("\r\n\r\n")
raise Exception('Error sending data to MCU\r\n\r\n')
line = ''
else:
line += char
if char == chr(62) and expected[i] == char:
char = ''
i += 1
class SerialTransport(AbstractTransport):
def __init__(self, port, baud, delay):
self.port = port
self.baud = baud
self.serial = None
self.delay = delay
try:
self.serial = serial.Serial(port, baud)
except serial.SerialException as e:
raise TransportError(e.strerror)
self.serial.timeout = 3
self.serial.interCharTimeout = 3
# zzz191021 juste après l'ouverture du port série, on attend le caractère '>'
line = ''
char = ''
i = -1
while char != chr(62): # '>'
char = self.read(1)
if char == '':
raise Exception('No proper answer from MCU')
line += char
i += 1
if args.verbose:
print("line: ." + line + ".")
def writeln(self, data, check=1):
# zzz191020 on fait une petite pause avant l'envoi de chaque ligne
sleep(self.delay)
if self.serial.inWaiting() > 0:
self.serial.flushInput()
if len(data) > 0 and not args.bar:
sys.stdout.write("\r\n->")
sys.stdout.write(data.split("\r")[0])
self.serial.write(data)
# zzz191021 Affiche ce que l'on a envoyé au NodeMCU
if args.verbose:
print("\n\nzwrite0952: {" + data + "\n}\n")
if check > 0:
self.performcheck(data)
elif not args.bar:
sys.stdout.write(" -> send without check")
def read(self, length):
return self.serial.read(length)
def close(self):
self.serial.flush()
self.serial.close()
class TcpSocketTransport(AbstractTransport):
def __init__(self, host, port):
self.host = host
self.port = port
self.socket = None
try:
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error as e:
raise TransportError(e.strerror)
try:
self.socket.connect((host, port))
except socket.error as e:
raise TransportError(e.strerror)
# read intro from telnet server (see telnet_srv.lua)
self.socket.recv(50)
def writeln(self, data, check=1):
if len(data) > 0 and not args.bar:
sys.stdout.write("\r\n->")
sys.stdout.write(data.split("\r")[0])
self.socket.sendall(data)
if check > 0:
self.performcheck(data)
elif not args.bar:
sys.stdout.write(" -> send without check")
def read(self, length):
return self.socket.recv(length)
def close(self):
self.socket.close()
def decidetransport(cliargs):
if cliargs.ip:
data = cliargs.ip.split(':')
host = data[0]
if len(data) == 2:
port = int(data[1])
else:
port = 23
return TcpSocketTransport(host, port)
else:
return SerialTransport(cliargs.port, cliargs.baud, cliargs.delay)
if __name__ == '__main__':
# parse arguments or use defaults
parser = argparse.ArgumentParser(description='ESP8266 Lua script uploader.')
parser.add_argument('--bar', action='store_true', help='Show a progress bar for uploads instead of printing each line')
parser.add_argument('--delay', default=0.03, help='Delay in seconds between each write, default 0.03 sec.', type=float)
parser.add_argument('--delete', default=None, help='Delete a lua/lc file from device.')
parser.add_argument('--ip', default=None, help='Connect via telnet server (--ip IP[:port])')
parser.add_argument('--zrestart', action='store_true', help='Restart the NodeMCU.')
parser.add_argument('-a', '--append', action='store_true', help='Append source file to destination file.')
parser.add_argument('-b', '--baud', default=115200, help='Baudrate, default 115200')
parser.add_argument('-c', '--compile', action='store_true', help='Compile lua to lc after upload')
parser.add_argument('-d', '--dofile', action='store_true', help='Run the Lua script after upload')
parser.add_argument('-e', '--echo', action='store_true', help='Echo output of MCU until script is terminated.')
parser.add_argument('-f', '--src', default='main.lua', help='Source file on computer, default main.lua')
parser.add_argument('-i', '--id', action='store_true', help='Query the modules chip id.')
parser.add_argument('-l', '--list', action='store_true', help='List files on device')
parser.add_argument('-p', '--port', default='/dev/ttyUSB0', help='Device name, default /dev/ttyUSB0')
parser.add_argument('-r', '--restart', action='store_true', help='Restart MCU after upload')
parser.add_argument('-t', '--dest', default=None, help='Destination file on MCU, default to source file name')
parser.add_argument('-v', '--verbose', action='store_true', help="Show progress messages.")
parser.add_argument('-w', '--wipe', action='store_true', help='Delete all lua/lc files on device.')
args = parser.parse_args()
transport = decidetransport(args)
if args.bar and not tqdm_installed:
sys.stdout.write("You must install the tqdm library to use the bar feature\n")
sys.stdout.write("To install, at the prompt type: \"pip install tqdm\"\n")
sys.exit(0)
if args.list:
# zzz191020 Amélioré la sortie du listing des fichiers
transport.writeln("print('\\n-----');local l = file.list();for k,v in pairs(l) do print(k..', size:'..v)end;print('-----\\n')\r", 0)
while True:
char = transport.read(1)
if char == '' or char == chr(62): # '' or '>'
break
sys.stdout.write(char)
sys.exit(0)
if args.id:
transport.writeln("=node.chipid()\r", 0)
id=""
while True:
char = transport.read(1)
if char == '' or char == chr(62):
break
if char.isdigit():
id += char
print("\n"+id)
sys.exit(0)
# zzz191020 Ajouté la fonction restart seule
if args.zrestart:
transport.writeln("node.restart()\r")
sys.exit(0)
if args.wipe:
transport.writeln("local l = file.list();for k,v in pairs(l) do print(k)end\r", 0)
file_list = []
fn = ""
while True:
char = transport.read(1)
if char == '' or char == chr(62):
break
if char not in ['\r', '\n']:
fn += char
else:
if fn:
file_list.append(fn.strip())
fn = ''
for fn in file_list[1:]: # first line is the list command sent to device
if args.verbose:
sys.stderr.write("Delete file {} from device.\r\n".format(fn))
transport.writeln("file.remove(\"" + fn + "\")\r")
sys.exit(0)
if args.delete:
transport.writeln("file.remove(\"" + args.delete + "\")\r")
sys.exit(0)
if args.dest is None:
args.dest = basename(args.src)
# zzz191020 Affiche le fichier à envoyer
print("File: " + args.src)
# open source file for reading
try:
try:
f = open(args.src, "rt")
except:
import os
base_dir = os.path.dirname(os.path.realpath(__file__))
f = open(os.path.join(base_dir, args.src), "rt")
os.chdir(base_dir)
except:
sys.stderr.write("Could not open input file \"%s\"\n" % args.src)
sys.exit(1)
# Verify the selected file will not exceed the size of the serial buffer.
# The size of the buffer is 256. This script does not accept files with
# lines longer than 230 characters to have some room for command overhead.
num_lines = 0
for ln in f:
if len(ln) > 230:
sys.stderr.write("File \"%s\" contains a line with more than 240 "
"characters. This exceeds the size of the serial buffer.\n"
% args.src)
f.close()
sys.exit(1)
num_lines += 1
# Go back to the beginning of the file after verifying it has the correct
# line length
f.seek(0)
# set serial timeout
if args.verbose:
sys.stderr.write("Upload starting\r\n")
# remove existing file on device
if args.append==False:
if args.verbose:
sys.stderr.write("Stage 1. Deleting old file from flash memory")
transport.writeln("file.open(\"" + args.dest + "\", \"w\")\r")
transport.writeln("file.close()\r")
transport.writeln("file.remove(\"" + args.dest + "\")\r")
else:
if args.verbose:
sys.stderr.write("[SKIPPED] Stage 1. Deleting old file from flash memory [SKIPPED]")
# read source file line by line and write to device
if args.verbose:
sys.stderr.write("\r\nStage 2. Creating file in flash memory and write first line")
if args.append:
transport.writeln("file.open(\"" + args.dest + "\", \"a+\")\r")
else:
transport.writeln("file.open(\"" + args.dest + "\", \"w+\")\r")
line = f.readline()
if args.verbose:
sys.stderr.write("\r\nStage 3. Start writing data to flash memory...")
if args.bar:
for i in tqdm(range(0, num_lines)):
transport.writer(line.strip())
line = f.readline()
else:
while line != '':
transport.writer(line.strip())
line = f.readline()
# close both files
f.close()
if args.verbose:
sys.stderr.write("\r\nStage 4. Flush data and closing file")
transport.writeln("file.flush()\r")
transport.writeln("file.close()\r")
# compile?
if args.compile:
if args.verbose:
sys.stderr.write("\r\nStage 5. Compiling")
transport.writeln("node.compile(\"" + args.dest + "\")\r")
transport.writeln("file.remove(\"" + args.dest + "\")\r")
# restart or dofile
if args.restart:
transport.writeln("node.restart()\r")
if args.dofile: # never exec if restart=1
transport.writeln("dofile(\"" + args.dest + "\")\r", 0)
if args.echo:
if args.verbose:
sys.stderr.write("\r\nEchoing MCU output, press Ctrl-C to exit")
while True:
sys.stdout.write(transport.read(1))
# close serial port
transport.close()
# flush screen
sys.stdout.flush()
sys.stderr.flush()
if not args.bar:
sys.stderr.write("\r\n--->>> All done <<<---\r\n")

View File

@@ -0,0 +1,29 @@
-- Scripts pour régler l'horloge quand on est connecté en WIFI
-- Permet aussi de 'compresser' le unix time afin de prendre moins de place dans les strings
print("\n set_time.lua zf190217.1426 \n")
--source: https://www.freeformatter.com/epoch-timestamp-to-date-converter.html
ztime2019 = 1546300800 -- Unix time pour le 1.1.2019
function set_time()
sntp.sync(nil, nil, nil, 1)
end
function ztime_compress(ztime_long)
return ztime_long - ztime2019
end
function ztime_uncompress(ztime_short)
return ztime_short + ztime2019
end
function ztime_format(ztime)
tm = rtctime.epoch2cal(ztime + 3600)
return(string.format("%04d/%02d/%02d %02d:%02d:%02d", tm["year"], tm["mon"], tm["day"], tm["hour"], tm["min"], tm["sec"]))
end
set_time()
print(ztime_format(rtctime.get()))

View File

@@ -0,0 +1,52 @@
-- Scripts pour régler l'horloge quand on est connecté en WIFI
-- Permet aussi de 'compresser' le unix time afin de prendre moins de place dans les strings
-- je suis en train de faire une version plus économique au niveau RAM (voir à la fin)
print("\n set_time2.lua zf200611.1926 \n")
--source: https://www.freeformatter.com/epoch-timestamp-to-date-converter.html
ztime2019 = 1546300800 -- Unix time pour le 1.1.2019
function set_time()
sntp.sync(nil, nil, nil, 1)
end
function ztime_compress(ztime_long)
return ztime_long - ztime2019
end
function ztime_uncompress(ztime_short)
return ztime_short + ztime2019
end
function ztime_format(ztime)
tm = rtctime.epoch2cal(ztime + 3600)
return(string.format("%04d/%02d/%02d %02d:%02d:%02d", tm["year"], tm["mon"], tm["day"], tm["hour"], tm["min"], tm["sec"]))
end
set_time()
print(ztime_format(rtctime.get()))
-- function ztime_stamp() return tmr.now()/1000000 end
-- sntp.sync(nil, nil, nil, 1)
--
-- function ztime_format(ztime)
-- tm = rtctime.epoch2cal(ztime + 3600)
-- return(string.format("%04d/%02d/%02d %02d:%02d:%02d", tm["year"], tm["mon"], tm["day"], tm["hour"], tm["min"], tm["sec"]))
-- end
--
-- print(ztime_format(rtctime.get()+3600))
--
-- zsec, zusec = rtctime.get()
--
-- print(zsec, zusec)
-- zsec=zsec+3600+zusec/1000000
-- print(ztime_format(zsec))
--
-- print(zsec)
-- znanosec= zsec*1000000000
-- print(znanosec)

View File

@@ -0,0 +1,93 @@
-- Serveur telnet pour connexion en remote WIFI, NOUVELLE VERSION !
-- source: https://github.com/nodemcu/nodemcu-firmware/blob/master/lua_examples/telnet/telnet.lua
print("\n telnet_srv2.lua zf191020.1932 \n")
local node, table, tmr, wifi, uwrite, tostring =
node, table, tmr, wifi, 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
node.output(nil)
end
--zzz
local function zconnection(s)
print("Welcome 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("Telnet server running...\nUsage: telnet -rN ip\n")

View File

@@ -0,0 +1,40 @@
% Template MATLAB code for visualizing correlated data using the
% SCATTER function.
% zf190728.1213
% Prior to running this MATLAB code template, assign the channel variables.
% Set 'readChannelID' to the channel ID of the channel to read from.
% Also, assign the read field IDs to the variables 'fieldID1', and 'fieldID2'.
% Replace the [] with channel ID to read data from:
readChannelID = []];
fieldID1 = 1;
fieldID2 = 2;
fieldID3 = 3;
% Channel Read API Key
% If your channel is private, then enter the read API
% Key between the '' below:
readAPIKey = '';
%% Read Data %%
nbMesures = 200
% Read 1 data variable
[data1, time1] = thingSpeakRead(readChannelID, 'Field', fieldID1, 'NumPoints', nbMesures, 'ReadKey', readAPIKey);
% Read 2 data variable
[data2, time2] = thingSpeakRead(readChannelID, 'Field', fieldID2, 'NumPoints', nbMesures, 'ReadKey', readAPIKey);
% Read 3 data variable
[data3, time3] = thingSpeakRead(readChannelID, 'Field', fieldID3, 'NumPoints', nbMesures, 'ReadKey', readAPIKey);
%% Visualize Data %%
plot(time1,data1, time2,data2, time3,data3);
legend({'Tint 1er','Text sud','Text nord'});
xlabel('Time (GMT ! )');
ylabel('Temperature °C');
title('Mesures température 1023 Crissier');

View File

@@ -0,0 +1,39 @@
#!/bin/bash
# Petit script pour télécharger facilement tout le binz
#zf191023.0959
# S'il y a des erreurs lors d'un téléchargement, il faut simplement augmenter un peu le délai !
# Il est préférable de télécharger en premier les *gros* fichiers .lua !
# ATTENTION: cela efface tout le NodeMCU !
echo "attention il n'est PAS à jour, zf191023.0959 !"
exit
luatool_tty="/dev/cu.wchusbserial1410"
echo ""
read -p "ATTENTION, cela va effacer tout le NodeMCU !"
read -p "Etes-vous vraiment certain ?"
chmod +x luatool.py
./luatool.py --port $luatool_tty -w
./luatool.py --port $luatool_tty -l
read -p "Est-ce bien vide ?"
./luatool.py --port $luatool_tty --bar --delay 0.06 -f telnet_srv2.lua
./luatool.py --port $luatool_tty --bar --delay 0.001 -f boot.lua
./luatool.py --port $luatool_tty --bar --delay 0.001 -f boot2.lua
./luatool.py --port $luatool_tty --bar --delay 0.03 -f flash_led_xfois.lua
./luatool.py --port $luatool_tty --bar --delay 0.001 -f secrets_energy.lua
./luatool.py --port $luatool_tty --bar --delay 0.001 -f wifi_ap_stop.lua
./luatool.py --port $luatool_tty --bar --delay 0.001 -f wifi_cli_conf.lua
./luatool.py --port $luatool_tty --bar --delay 0.001 -f wifi_cli_start.lua
./luatool.py --port $luatool_tty --bar --delay 0.001 -f wifi_info.lua
./luatool.py --port $luatool_tty -l
read -p "Pas eu d'erreur, on part à fond avec le init.lua ?"
./luatool.py --port $luatool_tty --bar --delay 0.001 -f initz.lua -t init.lua
echo -e "\nC'est tout bon ;-)"

View File

@@ -0,0 +1,159 @@
-- Petit WEB IDE tout simple autonome
-- ATTENTION: tourne sur le port 88 !
print("\n _web_ide2.lua zf181221.1137 \n")
--[[
XChip's NodeMCU IDE
Create, Edit and run NodeMCU files using your webbrowser.
Examples:
http://<mcu_ip>/ will list all the files in the MCU
http://<mcu_ip>/newfile.lua displays the file on your browser
http://<mcu_ip>/newfile.lua?edit allows to creates or edits the specified script in your browser
http://<mcu_ip>/newfile.lua?run it will run the specified script and will show the returned value
]]--
srv=net.createServer(net.TCP)
srv:listen(88,function(conn)
local rnrn=0
local Status = 0
local DataToGet = 0
local method=""
local url=""
local vars=""
conn:on("receive",function(conn,payload)
if Status==0 then
_, _, method, url, vars = string.find(payload, "([A-Z]+) /([^?]*)%??(.*) HTTP")
print(method, url, vars)
end
if method=="POST" then
if Status==0 then
--print("status", Status)
_,_,DataToGet, payload = string.find(payload, "Content%-Length: (%d+)(.+)")
if DataToGet~=nil then
DataToGet = tonumber(DataToGet)
--print(DataToGet)
rnrn=1
Status = 1
else
print("bad length")
end
end
-- find /r/n/r/n
if Status==1 then
--print("status", Status)
local payloadlen = string.len(payload)
local mark = "\r\n\r\n"
local i
for i=1, payloadlen do
if string.byte(mark, rnrn) == string.byte(payload, i) then
rnrn=rnrn+1
if rnrn==5 then
payload = string.sub(payload, i+1,payloadlen)
file.open(url, "w")
file.close()
Status=2
break
end
else
rnrn=1
end
end
if Status==1 then
return
end
end
if Status==2 then
--print("status", Status)
if payload~=nil then
DataToGet=DataToGet-string.len(payload)
--print("DataToGet:", DataToGet, "payload len:", string.len(payload))
file.open(url, "a+")
file.write(payload)
file.close()
else
conn:send("HTTP/1.1 200 OK\r\n\r\nERROR")
Status=0
end
if DataToGet==0 then
conn:send("HTTP/1.1 200 OK\r\n\r\nOK")
Status=0
end
end
return
end
DataToGet = -1
if url == "favicon.ico" then
conn:send("HTTP/1.1 404 file not found")
return
end
conn:send("HTTP/1.1 200 OK\r\n\r\n")
-- it wants a file in particular
if url~="" and vars=="" then
DataToGet = 0
return
end
conn:send("<html><body><h1>NodeMCU IDE</h1>")
if vars=="edit" then
conn:send("<script>function tag(c){document.getElementsByTagName('w')[0].innerHTML=c};\n")
conn:send("var x=new XMLHttpRequest()\nx.onreadystatechange=function(){if(x.readyState==4) document.getElementsByName('t')[0].value = x.responseText; };\nx.open('GET',location.pathname,true)\nx.send()</script>")
conn:send("<h2><a href='/'>Back to file list</a>\n")
conn:send("<br><br><button onclick=\"tag('Saving');x.open('POST',location.pathname,true);\nx.onreadystatechange=function(){if(x.readyState==4) tag(x.responseText);};\nx.send(new Blob(")
conn:send("[document.getElementsByName('t')[0].value],{type:'text/plain'}));\">Save</button><a href='?run'>run</a><w></w>")
conn:send("</h2><br><textarea name=t cols=110 rows=50></textarea></br>")
end
if vars=="run" then
conn:send("<verbatim>")
local st, result=pcall(dofile, url)
conn:send(tostring(result))
conn:send("</verbatim>")
end
if url=="" then
local l = file.list();
for k,v in pairs(l) do
conn:send("<a href='"..k.."?edit'>"..k.."</a>, size:"..v.."<br>")
end
end
conn:send("</body></html>")
end)
conn:on("sent",function(conn)
if DataToGet>=0 and method=="GET" then
if file.open(url, "r") then
file.seek("set", DataToGet)
local line=file.read(512)
file.close()
if line then
conn:send(line)
DataToGet = DataToGet + 512
if (string.len(line)==512) then
return
end
end
end
end
conn:close()
end)
end)
print("listening, free:", node.heap())

View File

@@ -0,0 +1,67 @@
-- petit script de serveur WEB avec Active Server Page ZYX
-- permet d'exécuter du code LUA inline dans l'HTML !
print("\n web_srv2.lua zf200112.1926 \n")
-- envoie sur le port ouvert mais depuis l'environnement global !
function zout(zstring)
if string.len(zstring) > 0 then
zzclient:send(zstring) -- envoie le résultat du code lua inline
end
end
-- envoie un fichier HTML sur le port. ATTENTION: longueur de la ligne maximale de 1'024 bytes !
function send_file(zclient, zfilename)
print("start send html...")
zclient:send("HTTP/1.1 200 OK\n")
zclient:send("Content-Type: text/html\n\n")
zzclient = zclient -- export le port sur l'environnement global !
if zfilename == "" then zfilename = "z_index.html" end
file_web = file.open(zfilename, "r")
if file_web then
repeat
local line = file_web:readline()
if line then
if string.find(line, "<%%") then
flag_lua_code = true -- bascule sur le code lua inline
lua_code = ""
elseif string.find(line, "%%>") then
flag_lua_code = false -- revient sur le code HTML
loadstring(lua_code)() --on exécute ici le code lua inline !
lua_code = nil
elseif flag_lua_code then
lua_code = lua_code..line -- récupère le code lua inline
else
zclient:send(line) -- envoie le code HTML
end
end
until not line
file_web:close() file_web = nil flag_lua_code=nil zzclient=nil
else
zclient:send("<html><h1>"..zfilename.." not found - 404 error</h1><a href='/'>Home</a><br></html>")
end
end
srv = net.createServer()
srv:listen(80, function(conn)
conn:on("receive", function(client, request)
_, _, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP")
if not string.find(request, "/favicon.ico") then
print("coucou")
if (method == nil) then
_, _, method, path = string.find(request, "([A-Z]+) (.+) HTTP")
end
print("method: ", method) print("path: ", path) print("vars: ", vars)
_GET = {}
if (vars ~= nil) then
for k, v in string.gmatch(vars, "(%w+)=(%w+)&*") do
_GET[k] = v
print(k..": "..v)
end
end
file_html=string.gsub(path, "/", "")
send_file(client, file_html) file_html=nil _GET=nil
end
end)
conn:on("sent", function(c) c:close() end)
end)

View File

@@ -0,0 +1,10 @@
-- Démarre le WIFI en mode AP
print("\n wifi_ap_stop.lua zf180824.2000 \n")
local zmodewifi=wifi.getmode()
if zmodewifi == wifi.SOFTAP then
wifi.setmode(wifi.NULLMODE)
elseif zmodewifi == wifi.STATIONAP then
wifi.setmode(wifi.STATION)
end
print("WIFI AP arrêté")

View File

@@ -0,0 +1,11 @@
-- Petit script pour configurer le client WIFI du NodeMCU
function wifi_cli_conf()
print("\n wifi_cli_conf.lua zf190726.1912 \n")
-- les secrets sont maintenant initialisés par boot.lua !
wifi.sta.config{ssid=cli_ssid, pwd=cli_pwd, save=true}
end
wifi_cli_conf()
wifi_cli_conf=nil

View File

@@ -0,0 +1,20 @@
-- Petit script pour connecter le NodeMCU sur un AP Wifi avec l'accompte sauvé en EEPROM
function wifi_cli_start()
print("\n wifi_cli_start.lua zf190310.1519 \n")
local zmodewifi=wifi.getmode()
if zmodewifi == wifi.NULLMODE then
print("WIFI mode CLI only")
wifi.setmode(wifi.STATION)
elseif zmodewifi == wifi.SOFTAP then
print("WIFI mode AP+CLI")
wifi.setmode(wifi.STATIONAP)
end
wifi.sta.autoconnect(1)
wifi.sta.connect()
--f= "wifi_get_ip.lua" if file.exists(f) then dofile(f) end
end
wifi_cli_start()
wifi_cli_start=nil

View File

@@ -0,0 +1,33 @@
-- Petit script pour afficher les infos actuel du WIFI
print("\n wifi_info.lua zf190727.1220 \n")
local zmodewifi=wifi.getmode()
--wifi.NULLMODE, wifi.STATION, wifi.SOFTAP, wifi.STATIONAP
if zmodewifi == wifi.NULLMODE then
print("WIFI OFF")
elseif zmodewifi == wifi.STATION then
print("WIFI mode CLI")
print("Connected IP:\n",wifi.sta.getip())
local sta_config=wifi.sta.getconfig(true)
print("Current client config:")
print("\tssid:", sta_config.ssid)
print("\tpassword:", sta_config.pwd)
print("\tbssid:", sta_config.bssid)
elseif zmodewifi == wifi.SOFTAP then
print("WIFI mode AP")
print("AP MAC:\n",wifi.ap.getmac())
print("AP IP:\n",wifi.ap.getip())
print("AP Connect:\n",wifi.ap.getconfig())
elseif zmodewifi == wifi.STATIONAP then
print("WIFI mode CLI+AP")
print("Connected IP:\n",wifi.sta.getip())
local sta_config=wifi.sta.getconfig(true)
print("Current client config:")
print("\tssid:", sta_config.ssid)
print("\tpassword:", sta_config.pwd)
print("\tbssid:", sta_config.bssid)
print("AP MAC: ", wifi.ap.getmac())
print("AP IP: ", wifi.ap.getip())
end

View File

@@ -0,0 +1,103 @@
<!DOCTYPE html>
<!-- ATTENTION, la longueur des lignes DOIT être <128 ! -->
<html lang="fr" dir="ltr">
<head>
<meta charset='utf-8' name='viewport' content='width=device-width, initial-scale=1.0'>
<%
zout("<title>"..node_id.."</title>")
%>
</head>
<body>
<%
zout("<h1>"..node_id.."&nbsp;&nbsp;&nbsp; 200118.1804 </h1>")
%>
<a href="/">Home...</a><br>
<h2>Menu:</h2>
<h3>
LED
<a href="api_sonoff.html?LED=on"> On</a>
<a href="api_sonoff.html?LED=off"> Off</a><br>
<a href="disp_temp.html">Affichage de la température et humidité</a><br>
<br>
<a href="z_index.html?SetupWIFI=true">Wifi setup</a><br>
</h3>
<%
if _GET.SetupWIFI == "true" then
print("On demande le setup wifi depuis le browser !")
wifi_setup_ok=(math.floor(100*node.random()))
zout("<br><br>Etes-vous vraiment certain ?<br>Si oui, faites: ")
zout('<a href="/?SetupWIFI='..wifi_setup_ok..'"> Ok</a><br><br>')
end
%>
<%
if (wifi_setup_ok ~= nil) and (_GET.SetupWIFI == tostring(wifi_setup_ok)) then
print("On confirme le setup wifi depuis le browser !")
zout("<br><br>Choisir comme WIFI AP: setup_gadget puis aller sur: http://192.168.4.1<br><br>")
file.putcontents("_setup_wifi_", "toto")
tmr.create():alarm(5*1000, tmr.ALARM_SINGLE, function()
print("on restart pour le setup wifi")
wifi.sta.config{ssid="", pwd="", auto=true, save=true}
wifi.sta.autoconnect(1) wifi.sta.connect()
node.restart()
end)
end
%>
<%
if _GET.RESTART == "true" then
print("oups restart...")
zout("<br><br>oups restart...<br><br>")
tmr.create():alarm(5*1000, tmr.ALARM_SINGLE, function()
print("on restart...")
node.restart()
end)
end
%>
<%
zout("Etat de la LED:<nsp>")
if gpio.read(zLED) == 1 then zout("OFF") else zout("ON") end
zout("<br>")
%>
<%
if zRELAY ~= nil then
zout("Etat du RELAY:<nsp>")
if gpio.read(zRELAY) == 0 then zout("OFF") else zout("ON") end
zout("<br>")
end
%>
<%
a,b,c = wifi.sta.getip()
if a ~= nil then
zout("<br>IP: "..a.."<br>\n".."MASK: "..b.."<br>\n".."GATEWAY: "..c.."<br>\n")
a=nil b=nil c=nil
end
collectgarbage() zout("RAM: "..node.heap().."<br>")
%>
<%
zout("<br>Etat des GLOBALS !<br>\n")
zout("<table>\n")
for k,v in pairs(_G) do
if k ~= "lua_code" then
v = tostring(v)
zout("<tr>")
zout("<td>"..k.."</td>") zout("<td>"..v.."</td>")
zout("</tr>\n")
end
end
zout("</table>")
%>
<br><br><a href="/?RESTART=true"> Restart !</a><br>
</body>
</html>

View File

@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="fr" dir="ltr">
<head>
<meta charset='utf-8' name='viewport' content='width=device-width, initial-scale=1.0'>
<title>ESP8266 page 1</title>
</head>
<body>
<h1>ESP8266 page 1 190127.1445</h1>
<br>
Coucou c'est la page 1 !<br>
<a href="/">Retour à la home page...</a><br><br><br>
La température est:
<%
ztemp=ztemp+1
zout(ztemp.."°C")
%>
<br>Mais il fait encore trop froid !<br>
</body>
</html>

View File

@@ -0,0 +1,51 @@
<!DOCTYPE html>
<html lang="fr" dir="ltr">
<head>
<meta charset='utf-8' name='viewport' content='width=device-width, initial-scale=1.0'>
<title>ESP8266 page 2</title>
</head>
<body>
<h1>ESP8266 page 2 190127.1449</h1>
<br>
Coucou c'est la page 2 !<br>
<a href="/">Retour à la home page...</a><br><br><br>
Voici un tableau dynamique écrit en Lua inline.<br><br>
Le code Lua pour créer ce tableau se trouve dans le code HTML de cette page et est exécuté sur le NodeMCU.<br>
Les données du tableau viennent du NodeMCU !<br><br>
<%
-- création du tableau sur le NodeMCUjuste juste pour la démo ici !
zmac_adrs={}
zmac_adrs["b8:d7:af:a6:bd:86"]={["zname"]="S7 zf", ["zrssi"]=45, ["ztime"]="12:03:36"}
zmac_adrs["cc:c0:79:7d:f5:d5"]={["zname"]="S7 Mélanie", ["zrssi"]=50, ["ztime"]="14:23:46"}
zmac_adrs["5c:f9:38:a1:f7:f0"]={["zname"]="MAC zf", ["zrssi"]=40, ["ztime"]="11:53:16"}
zmac_adrs["d8:30:62:5a:d6:3a"]={["zname"]="IMAC Maman", ["zrssi"]=55, ["ztime"]="17:07:23"}
%>
<table border='1'>
<tr>
<th>MAC</th><th>Name</th><th>RSSI</th><th>Time</th>
</tr>
<%
for k, v in pairs(zmac_adrs) do
zout("<tr>\n")
zout("\t<td>" .. k .. "</td>\n")
zout("\t<td>" .. tostring(zmac_adrs[k]["zname"]) .. "</td>\n")
zout("\t<td>" .. tostring(zmac_adrs[k]["zrssi"]) .. "</td>\n")
zout("\t<td>" .. tostring(zmac_adrs[k]["ztime"]) .. "</td>\n")
zout("</tr>\n")
end
%>
</table>
<%
-- libère la mémoire du tableau sur le NodeMCU qui avait été créé pour la démo ici !
zmac_adrs=nil
%>
</body>
</html>

View File

@@ -0,0 +1,50 @@
<!DOCTYPE html>
<html lang="fr" dir="ltr">
<head>
<meta charset='utf-8' name='viewport' content='width=device-width, initial-scale=1.0'>
<title>ESP8266 page 3</title>
</head>
<body>
<h1>ESP8266 page 3 190505.1156</h1>
<br>
Coucou c'est la page 3 !<br>
<a href="/">Retour à la home page...</a><br><br><br>
Voici le résultat du capteur non linéaire corrigé avec une table
d'interpolation dans un fichier .csv sur la flash.<br><br>
Le code Lua pour afficher ce résultat se trouve dans le code HTML de cette page et est exécuté sur le NodeMCU.<br>
Les données viennent du NodeMCU !<br><br>
<%
zout("Il reste: "..node.heap().." de RAM !<br><br>\n")
%>
<%
zx0=83
get_correction(zx0)
zout("la valeur corrigée de "..zx0.." est "..zy0.."<br>")
%>
<%
zx0=91
get_correction(zx0)
zout("la valeur corrigée de "..zx0.." est "..zy0.."<br>")
%>
<%
zx0=100
get_correction(zx0)
zout("la valeur corrigée de "..zx0.." est "..zy0.."<br>")
%>
<br>Yeah... cela fonctionne vachement bien !<br><br>
<%
zout("Il reste: "..node.heap().." de RAM !<br><br>\n")
%>
</body>
</html>

View File

@@ -0,0 +1,53 @@
<!DOCTYPE html>
<html lang="fr" dir="ltr">
<head>
<meta charset='utf-8' name='viewport' content='width=device-width, initial-scale=1.0'>
<title>ESP8266 page 3</title>
</head>
<body>
<h1>ESP8266 page 4 190726.1955</h1>
<br>
Web service concentrateur de mesures de température !<br>
<a href="/">Retour à la home page...</a><br><br><br>
Test d'un web service qui fonctionne avec l'Active Server Page ZYX.<br><br>
Le code Lua pour afficher ce résultat se trouve dans le code HTML de cette page et est exécuté sur le NodeMCU.<br>
Les données viennent du NodeMCU !<br><br>
<%
zout("Il reste: "..node.heap().." de RAM !<br><br>\n")
%>
Les arguments du web service (GET) sont:<br><br>
<%
if (vars ~= nil) then
zout("<br>vars: "..vars.."<br>")
for k, v in string.gmatch(vars, "(%w+)=(%w+)&*") do
_GET[k] = v
zout(k..": "..v.."<br>")
if k == "field1" then
ztemp1_conc = v
elseif k == "field2" then
ztemp2_conc = v
elseif k == "field3" then
ztemp3_conc = v
end
end
end
zout("<br>Les températures récupérées sont: "..ztemp1_conc..", "..ztemp2_conc..", "..ztemp3_conc)
%>
<br><br>Yeah... cela fonctionne vachement bien !<br><br>
<%
zout("Il reste: "..node.heap().." de RAM !<br><br>\n")
%>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

View File

@@ -0,0 +1,48 @@
#!/bin/bash
# Petit script pour télécharger facilement tout le binz via le port série
#zf191228.2313
# S'il y a des erreurs lors d'un téléchargement, il faut simplement augmenter un peu le délai !
# Il est préférable de télécharger en premier les *gros* fichiers .lua !
# ATTENTION: cela efface tout le NodeMCU !
luatool_tty="/dev/cu.wchusbserial1410"
echo ""
read -p "ATTENTION, cela va effacer tout le NodeMCU !"
read -p "Etes-vous vraiment certain ?"
chmod +x luatool.py
./luatool.py --port $luatool_tty -w
./luatool.py --port $luatool_tty -l
read -p "Est-ce bien vide ?"
./luatool.py --port $luatool_tty --bar -f z_index.html
./luatool.py --port $luatool_tty --bar -f wifi_init.lua
./luatool.py --port $luatool_tty --bar -f wifi_info.lua
./luatool.py --port $luatool_tty --bar -f wifi_clear.html
./luatool.py --port $luatool_tty --bar -f web_srv2.lua
./luatool.py --port $luatool_tty --bar -f web_ide2.lua
./luatool.py --port $luatool_tty --bar -f telnet_srv2.lua
./luatool.py --port $luatool_tty --bar -f set_time.lua
./luatool.py --port $luatool_tty --bar -f secrets_wifi.lua
./luatool.py --port $luatool_tty --bar -f secrets_project.lua
./luatool.py --port $luatool_tty --bar -f head.lua
./luatool.py --port $luatool_tty --bar -f eus_params.lua
./luatool.py --port $luatool_tty --bar -f disp_temp.html
./luatool.py --port $luatool_tty --bar -f dir2.lua
./luatool.py --port $luatool_tty --bar -f cat.lua
./luatool.py --port $luatool_tty --bar -f boot2.lua
./luatool.py --port $luatool_tty --bar -f boot.lua
./luatool.py --port $luatool_tty --bar -f 0_send_data.lua
#./luatool.py --port $luatool_tty --bar -f 0_htu21d.lua
./luatool.py --port $luatool_tty --bar -f 0_cron.lua
./luatool.py --port $luatool_tty -l
read -p "Pas eu d'erreur, on part à fond avec le init.lua ?"
./luatool.py --port $luatool_tty --bar -f initz.lua -t init.lua
./luatool.py --port $luatool_tty -l
echo -e "\nC'est tout bon ;-)"

View File

@@ -0,0 +1,45 @@
-- Petit script pour afficher les infos actuel du WIFI
print("\n wifi_info.lua zf200106.1803 \n")
function wifi_info()
local zmodewifi=wifi.getmode()
--wifi.NULLMODE, wifi.STATION, wifi.SOFTAP, wifi.STATIONAP
if zmodewifi == wifi.NULLMODE then
print("WIFI OFF")
elseif zmodewifi == wifi.STATION then
print("WIFI mode CLI")
print("Connected IP:\n",wifi.sta.getip())
local sta_config=wifi.sta.getconfig(true)
print("Current client config:")
print("\tssid:", sta_config.ssid)
print("\tpassword:", sta_config.pwd)
print("\tbssid:", sta_config.bssid)
elseif zmodewifi == wifi.SOFTAP then
print("WIFI mode AP\n")
print("AP IP: ", wifi.ap.getip())
print("Current AP config:")
local ap_config=wifi.ap.getconfig(true)
print("\tssid:", ap_config.ssid)
print("\tpassword:", ap_config.pwd)
print("\tbssid:", wifi.ap.getmac())
elseif zmodewifi == wifi.STATIONAP then
print("WIFI mode CLI+AP\n")
print("CLIENT IP:\n",wifi.sta.getip())
local sta_config=wifi.sta.getconfig(true)
print("Current CLIENT config:")
print("\tssid:", sta_config.ssid)
print("\tpassword:", sta_config.pwd)
print("\tbssid:", sta_config.bssid.."\n")
print("AP IP: ", wifi.ap.getip())
print("Current AP config:")
local ap_config=wifi.ap.getconfig(true)
print("\tssid:", ap_config.ssid)
print("\tpassword:", ap_config.pwd)
print("\tbssid:", wifi.ap.getmac())
end
wifi_info=nil
end
wifi_info()

View File

@@ -0,0 +1,92 @@
-- Petit script pour initaliser la couche WIFI
function wifi_init()
print("\n wifi_init.lua zf200621.1608 \n")
f= "secrets_wifi.lua" if file.exists(f) then dofile(f) end
f= "secrets_project.lua" if file.exists(f) then dofile(f) end
function wifi_init_end()
tmr_wifi_init1:unregister() i=nil
f= "wifi_info.lua" if file.exists(f) then dofile(f) end
f=nil secrets_wifi=nil cli_pwd=nil cli_ssid=nil
tmr_wifi_init1=nil wifi_init=nil
print(node.heap()) collectgarbage() print(node.heap())
-- f= "telnet_srv2.lua" if file.exists(f) then dofile(f) end
f="0_tst5_socat.lua" if file.exists(f) then dofile(f) end
-- f= "web_srv2.lua" if file.exists(f) then dofile(f) end
print(node.heap()) collectgarbage() print(node.heap())
zdelay=1 if reset_reason=="seconde_chance" then zdelay=20 end
tmr_wifi_init3=tmr.create()
tmr_wifi_init3:alarm(zdelay*1000, tmr.ALARM_SINGLE, function()
gpio.write(zLED, gpio.LOW)
f= "boot.lua" if file.exists(f) then dofile(f) end
tmr_wifi_init3:unregister() tmr_wifi_init3=nil wifi_init_end=nil
reset_reason=nil zdelay=nil
end)
end
if file.exists("_setup_wifi_") then
print("setup wifi...")
file.remove("_setup_wifi_")
wifi.sta.config{ssid="", pwd=""} wifi.sta.connect()
if zLED == nil then zLED = 4 end
gpio.write(zLED, gpio.HIGH) gpio.mode(zLED, gpio.OUTPUT)
tmr_wifi_init4=tmr.create()
tmr_wifi_init4:alarm(0.1*1000, tmr.ALARM_AUTO , function()
gpio.write(zLED, gpio.LOW) tmr.delay(10000) gpio.write(zLED, gpio.HIGH)
end)
tmr.create():alarm(90*1000, tmr.ALARM_SINGLE, function()
node.restart()
end)
enduser_setup.start(function()
print("on est sortit du setup wifi et on restart !")
node.restart()
end)
print("setup gadget lancé...")
else
wifi.setmode(wifi.STATION,true)
wifi.sta.config{ssid=cli_ssid, pwd=cli_pwd} wifi.sta.connect()
-- wifi.setmode(wifi.STATIONAP,true)
-- if node_id == nil then node_id = "generic" ap_pwd = "12345678" end
-- wifi.ap.config({ ssid = ap_ssid.."_"..node_id, pwd = ap_pwd, save=true })
-- ap_ssid=nil ap_pwd=nil
-- tmr_wifi_init2=tmr.create()
-- tmr_wifi_init2:alarm(60*1000, tmr.ALARM_SINGLE, function()
-- print("BOOOOUM, y'a plus de AP WIFI !")
-- wifi.setmode(wifi.STATION,true) tmr_wifi_init2=nil
-- print(node.heap()) collectgarbage() print(node.heap())
-- end)
gpio.write(zLED, gpio.HIGH) gpio.mode(zLED, gpio.OUTPUT) i=1
tmr_wifi_init1=tmr.create()
tmr_wifi_init1:alarm(1*1000, tmr.ALARM_AUTO , function()
gpio.write(zLED, gpio.LOW) tmr.delay(10000) gpio.write(zLED, gpio.HIGH)
if wifi.sta.getip() == nil then
print(i,"Connecting to AP...")
i=i+1
if i > 30 then
print("pas de wifi :-(")
file.putcontents("_setup_wifi_", "toto")
print("on restart pour le setup wifi")
node.restart()
--tmr_wifi_init2:unregister() tmr_wifi_init2=nil
--wifi.setmode(wifi.SOFTAP,true)
--wifi_init_end()
end
else
wifi_init_end()
end
end)
end
end
wifi_init()
--[[
file.putcontents("_setup_wifi_", "toto")
file.remove("eus_params.lua")
]]

View File

@@ -0,0 +1,28 @@
-- 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 zf200621.1942 \n")
gpio.write(zLED,1) gpio.mode(zLED,gpio.OUTPUT)
gpio.mode(zBTN,gpio.INT)
btn_time=tmr.now()
function z_btn_led (a,b,c)
--print("a: "..a..",b: "..b..",c: "..c)
if b-btn_time > 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
btn_time=b
print("verbose:",verbose)
end
end
gpio.trig(zBTN, "down", z_btn_led)

View File

@@ -0,0 +1,37 @@
-- Petit script pour faire office de crontab pour les mesures
print("\n 0_cron.lua zf200621.1936 \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
rt_launch()
-- http_post(influxdb_url,"energy,value=test1_"..yellow_id.." val=1")
-- http_post(influxdb_url,"energy,memory=cron1_"..yellow_id.." ram="..node.heap())
-- if yellow_id == 60 then http_post(influxdb_url,"energy,compteur=3 puissance="..zpower/1000) end
if yellow_id == 64 then http_post(influxdb_url,"energy,compteur=4 puissance="..zpower/1000) end
-- http_post(influxdb_url,"energy,value=test2_"..yellow_id.." val=2")
-- http_post(influxdb_url,"energy,value=test3_"..yellow_id.." val=3")
-- http_post(influxdb_url,"energy,value=test4_"..yellow_id.." val=4")
-- f = "0_zdyndns.lua" if file.exists(f) then dofile(f) end
-- f=nil
-- if verbose then print("End cron:") end
collectgarbage()
-- if verbose then print(node.heap()) end
end)
--[[
cron1:stop()
cron1:start()
]]

View File

@@ -0,0 +1,45 @@
-- 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 zf200621.2320 \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 local zurl=t_zurl[1] local zarg=t_zarg[1]
-- zarg=zarg.."\n".."energy,value=nb_waiting_"..yellow_id.." val="..#t_zurl
zarg=zarg.."\n".."energy,memory=zpost_"..yellow_id.." ram="..node.heap()
-- 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)
if debug_rec~=nil then debug_rec("HTTP request failed: ", code, data) end
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:") end
collectgarbage()
-- if verbose then print(node.heap()) end
end)
end
function http_post(zurl,zarg)
if #t_zurl <=10 then table.insert(t_zurl, zurl) table.insert(t_zarg, zarg) end
-- if verbose then print("Nb wait: "..#t_zurl) print(node.heap()) end
-- 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:") end
collectgarbage()
-- if verbose then print(node.heap()) end
end

View File

@@ -0,0 +1,148 @@
-- script telnet pour le socat
function telnet_listener(socket)
print("\n 0_rtelnet1.lua zf200621.2309 \n")
-- node, table, tmr, uwrite, tostring =
-- node, table, tmr, uart.write, tostring
print("................telnet_listener")
-- insert, remove, concat, heap, gc =
-- table.insert, table.remove, table.concat, node.heap, collectgarbage
fifo1, fifo1l, fifo2, fifo2l = {}, 0, {}, 0
-- local s -- s is a copy of the TCP socket if and only if sending is in progress
function flushGarbage()
if node.heap() < 13440 then collectgarbage() end
end
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
table.insert(fifo2,table.concat(fifo1))
fifo2l, fifo1, fifo1l = fifo2l + fifo1l, {}, 0
end
rec = table.remove(fifo2,1)..(table.remove(fifo2,1) or '') ..(table.remove(fifo2,1) or '') .. (table.remove(fifo2,1) or '')
fifo2l = fifo2l - #rec
flushGarbage()
if srv_rt:getpeer()~=nil then
s:send(rec)
end
end
local F1_SIZE = 256
function queueLine(str)
while #str > 0 do -- this is because str might be longer than the packet size!
k, l = F1_SIZE - fifo1l, #str
if #fifo1 >= 32 or (k < l and k < 16) then
table.insert(fifo2, table.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
table.insert(fifo1, chunk)
fifo1l = fifo1l + #chunk
end
if not s and socket then
s = socket
sendLine()
else
flushGarbage()
end
end
function receiveLine(s, line)
node.input(line)
end
function disconnect(_,zerr)
node.output(nil)
gpio.write(zLED, gpio.HIGH)
print("................disconnect")
if socket~=nil then
-- if http_post~=nil then http_post(influxdb_url,"energy,memory=srv_rt_no_nil_"..yellow_id.." ram="..node.heap()) end
print("................disconnect 2e", socket, socket:getpeer())
socket:on("connection", nil)
socket:on("reconnection", nil)
socket:on("disconnection", nil)
socket:on("receive", nil)
socket:on("sent", nil)
socket=nil
end
-- fifo1, fifo1l, fifo2, fifo2l, s = nil, nil, nil, nil, nil
print("disconnected... "..zerr..", "..node.heap())
-- if debug_rec~=nil then debug_rec("disconnect, disconnected, "..zerr..", "..node.heap()) end
-- node, table, tmr, uwrite, tostring = nil, nil, nil, nil, nil
-- insert, remove, concat, heap, gc = nil, nil, nil, nil, nil
-- fifo1, fifo1l, fifo2, fifo2l = nil, nil, nil, nil
-- rec = nil
-- s = nil
-- socket = nil
-- flushGarbage = nil
-- sendLine = nil
-- queueLine = nil
-- receiveLine = nil
-- zconnection = nil
-- disconnect = nil
-- -- telnet_listener=nil
fifo1, fifo1l, fifo2, fifo2l = nil, nil, nil, nil
rec = nil
k = nil
l = nil
s = nil
chunk = nil
socket = nil
flushGarbage = nil
sendLine = nil
queueLine = nil
receiveLine = nil
zconnection = nil
disconnect = nil
telnet_listener=nil
srv_rt=nil
-- collectgarbage()
rt_connect()
end
--zzz
function zconnection(s)
print("socket: ",socket)
if socket~=nil then
-- if http_post~=nil then http_post(influxdb_url,"energy,memory=srv_rt_no_nil_"..yellow_id.." ram="..node.heap()) end
print(socket:getpeer())
end
local zstr="zconnection, Oups, on ne devrait jamais passer par là to NodeMCU world."
print(zstr) if debug_rec~=nil then debug_rec(zstr) end
socket=nil
end
socket:on("connection", zconnection)
socket:on("receive", receiveLine)
socket:on("disconnection", disconnect)
socket:on("sent", sendLine)
node.output(queueLine, 0)
-- print(queueLine, 0)
end

View File

@@ -0,0 +1,115 @@
--[[
tests connection reverse telnet commande à faire tourner sur le GATEWAY !
1ere console
pour une liaison directe:
socat TCP-LISTEN:23064,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_tst5_socat.lua zf200621.2330 \n")
function rt_connect()
print("................rt_connect")
collectgarbage()
local zlaps=tmr.now()/1000000-ztime_connect
print("time of retry connect... "..zlaps)
-- if debug_rec~=nil then debug_rec("time of retry connect... "..zlaps..", "..node.heap()) end
if zlaps>1 then
local zstr="trying connect to "..console_host..":"..console_port..", "..node.heap()
-- if debug_rec~=nil then debug_rec(zstr) end
if verbose==verbose then
gpio.write(zLED, gpio.LOW) tmr.delay(10000) gpio.write(zLED, gpio.HIGH)
print(zstr)
end
if http_post~=nil then http_post(influxdb_url,"energy,memory=socat_try_con_"..yellow_id.." ram="..node.heap()) end
ztime_connect=tmr.now()/1000000
srv_rt=nil
srv_rt = net.createConnection(net.TCP, 0)
srv_rt:on("connection", function(sck)
print("................connection")
if debug_rec~=nil then debug_rec("rt_connect, srv_rt:on, connected on, "..node.heap()) end
collectgarbage()
-- if verbose then
gpio.write(zLED, gpio.LOW)
print("connected on "..console_host..":"..console_port..", "..node.heap())
print(node.heap())
-- end
if http_post~=nil then http_post(influxdb_url,"energy,memory=socat_connected_"..yellow_id.." ram="..node.heap()) end
dofile("0_rtelnet1.lua")
telnet_listener(sck)
print("Welcome to NodeMCU world.")
end)
srv_rt:on("reconnection", function(sck)
print(";;;;;;;;;;;;;;;;reconnection")
srv_rt:on("connection", nil)
srv_rt:on("reconnection", nil)
end)
-- srv_rt:on("disconnection", function(sck)
-- print(";;;;;;;;;;;;;;;;disconnection")
-- end)
--
-- srv_rt:on("receive", function(sck)
-- print(";;;;;;;;;;;;;;;;receive")
-- end)
--
-- srv_rt:on("sent", function(sck)
-- print(";;;;;;;;;;;;;;;;sent")
-- end)
srv_rt:connect(console_port,console_host)
else
print("on ne se reconnecte pas vite 1x...")
end
collectgarbage()
end
function rt_launch()
if http_post~=nil then http_post(influxdb_url,"energy,memory=tmr_socat1_"..yellow_id.." ram="..node.heap()) end
if srv_rt~=nil then
-- if http_post~=nil then http_post(influxdb_url,"energy,memory=srv_rt_no_nil_"..yellow_id.." ram="..node.heap()) end
if console_port ~= srv_rt:getpeer() then
rt_connect()
end
else
rt_connect()
end
end
-- tmr_socat1=tmr.create()
-- tmr_socat1:alarm(15*1000, tmr.ALARM_AUTO , rt_launch)
ztime_connect=tmr.now()/1000000-10
rt_launch()
print("Revers telnet server running...\n")

View File

@@ -0,0 +1,54 @@
-- Mesure la distance avec le module ultra-son
print("\n ultra_son.lua zf181026.1355 \n")
--Parametres pour le module ultra son
local ztrig=5
gpio.mode(ztrig, gpio.OUTPUT)
local fast_write = gpio.write
fast_write(ztrig, 0)
local zecho=6
gpio.mode(zecho, gpio.INT, gpio.PULLUP)
detectortimer1=tmr.create()
detectortimer2=tmr.create()
local fast_read = gpio.read
local ultra_son_start=0
local ultra_son_stop=0
--Function pour envoyer la pulse
function zmesure_pulse()
--t1=tmr.now()
-- fast_write(ztrig, 1)
-- fast_write(ztrig, 0)
--gpio.serout(ztrig,gpio.LOW,{1,10})
gpio.serout(ztrig,gpio.HIGH,{10,1})
--t2=tmr.now()
--print("durée: "..t2-t1-314)
end
--Fonction pour mesurer la pulse
function zmesure()
--print("pin: "..gpio.read(zecho))
if fast_read(zecho)==1 then
ultra_son_start=tmr.now()
else
ultra_son_stop=tmr.now()
print("Delta: "..ultra_son_stop-ultra_son_start)
-- zlength=math.floor(480*(ultra_son_stop-ultra_son_start)/2/10000)/100
zlength=480*(ultra_son_stop-ultra_son_start)/2/10000
-- if zlength>6 then zlength=0 end
disp_mesure()
end
end
gpio.trig(zecho,"both",zmesure)
-- à commenter après les tests de perf
function disp_mesure() print(zlength) end
tmr.alarm(detectortimer1, 1000, tmr.ALARM_AUTO, zmesure_pulse)

View File

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

View File

@@ -0,0 +1,192 @@
# Mesure d'énergie d'une installation monophasée
Version pour l'installation solaire qui se trouve sur le toit !
zf200607.1211
Profilage de fuites mémoire sur IoT avec Lua
https://docs.google.com/document/d/1H96RfhmMhTz6i1bq8uWTP3cOSOQD-78dgeGNKpzsJRg/edit?usp=sharing
**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

@@ -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,79 @@
zf200621.2337
srv_rt:on("connection", nil)
=node.heap()
rt_connect()
fifo1, fifo1l, fifo2, fifo2l = nil, nil, nil, nil
rec = nil
k = nil
l = nil
s = nil
chunk = nil
socket = nil
flushGarbage = nil
sendLine = nil
queueLine = nil
receiveLine = nil
zconnection = nil
disconnect = nil
telnet_listener=nil
srv_rt=nil
=node.heap()
=node.heap()
dofile("0_rtelnet1.lua")
=node.heap()
telnet_listener=nil
=node.heap()
srv_rt=nil
=node.heap()
for k,v in ipairs(debug.getregistry()) do print(k,v) end
node.stripdebug(3)
node.compile('0_tst4_socat.lua')
print(srv_rt)
print(srv_rt:getpeer())
srv_rt:close()
print(socket)
print(socket:getpeer())
socket:close()
verbose=true
node.output(nil)
http_post(influxdb_url,"energy,value=test1_"..yellow_id.." val=1") print("toto",node.heap(),#t_zurl)
=srv_rt:getaddr()
tmr_socat1:unregister()
for k,v in pairs(_G) do print(k,v) end
total_allocated, estimated_used = node.egc.meminfo()
print(total_allocated, estimated_used)
print(console_port)
srv_rt = nil collectgarbage()

View File

@@ -0,0 +1,292 @@
# Quelques commandes remote (luatool) à envoyer avec le plugin Atom-IDE-terminal de l'éditeur Atom
# zf200624.1854
Todo à faire pour ce projet !
???
# 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 #
################################
# pour les tests en direct sur la gateway
ssh ubuntu@www.zuzu-test.ml
socat TCP-LISTEN:23064,fork,reuseaddr STDIO
################################
# pour les tests en remote
killall -9 ssh
ssh ubuntu@www.zuzu-test.ml killall -9 socat
ssh ubuntu@www.zuzu-test.ml socat TCP-LISTEN:23064,reuseaddr,fork TCP-LISTEN:23000,reuseaddr,bind=127.0.0.1 &
# SHIFT+CMD+K SHIFT+CMD+K ALT+CMD+F
watch -n 1 'ssh ubuntu@www.zuzu-test.ml netstat -nat |grep 230'
# ALT+CMD+F CTRL+C ALT+CMD+F
export zIP="localhost"
export zport="23000"
ssh -N -L 23000:localhost:23000 ubuntu@www.zuzu-test.ml &
telnet -rN $zIP $zport
=node.heap()
~.
verbose=false
= node.bootreason()
# https://nodemcu.readthedocs.io/en/master/modules/node/#nodebootreason
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 0_get_power.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 -f 0_tst4_socat.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,66 @@
-- Scripts à charger après le boot pour démarrer son projet
function boot()
print("\n boot.lua zf200621.1939 \n")
print("On lance le boot...")
collectgarbage() print(node.heap())
local f
f = "0_http_post.lua" if file.exists(f) then dofile(f) end
collectgarbage() print(node.heap())
local _, boot_reason = node.bootreason()
zarg_boot= "energy,memory=boot_"..yellow_id.." ram="..node.heap().."\n"
zarg_boot=zarg_boot.."energy,value=boot_reason_"..yellow_id.." val="..boot_reason
http_post(influxdb_url,zarg_boot)
-- 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
collectgarbage() print(node.heap())
zpower=0
f="0_get_power.lua" if file.exists(f) then dofile(f) end
collectgarbage() print(node.heap())
f="0_cron.lua" if file.exists(f) then dofile(f) end
collectgarbage() print(node.heap())
verbose = true
print("verbose: ",verbose,"\nle boot est lancé...")
gpio.write(zLED, gpio.HIGH)
f=nil boot=nil
end
-- function debug_rec(zdebug)
-- local sec, usec = rtctime.get() local tm = rtctime.epoch2cal(sec + 2*3600)
-- local ztm = string.format("%04d/%02d/%02d %02d:%02d:%02d", tm["year"], tm["mon"], tm["day"], tm["hour"], tm["min"], tm["sec"])
-- file.open("00_debug.txt", "a+") file.writeline(ztm.."."..usec..", "..zdebug) file.close()
-- end
--
-- function rec_boot()
-- sntp.sync(nil, nil, nil, 1)
-- tmr_rec_boot1=tmr.create()
-- tmr_rec_boot1:alarm(1*1000, tmr.ALARM_AUTO, function()
-- print("beep...")
-- if rtctime.get() > 0 then
-- tmr_rec_boot1:unregister()
-- print("Voilà on à l'heure, on peut enregistrer la raison du boot...")
-- local _, zboot_reason, zboot_detail = node.bootreason()
-- debug_rec("boot reason: "..zboot_reason)
-- tmr_rec_boot1=nil rec_boot=nil
-- collectgarbage() print(node.heap())
-- end
-- end)
-- end
verbose=true
if rec_boot~=nil then rec_boot() end
boot()
collectgarbage() print(node.heap())
--[[
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 dir.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,52 @@
-- fonction dir_vers() pour afficher toutes les versions de tous les fichiers *.lua sur le NodeMCU !
-- fonction filec(fichier) pour afficher la version d'un seul fichiers sur le NodeMCU !
function dir3()
print("\n 0_dir3.lua zf200611.1714 \n")
function file_vers(name_file)
local z=""
if string.find(name_file,"%.lua") then
z=name_file..":"
-- print("fichier: "..name_file)
local f,i1,i2,j1,j2,k,t = f,i1,i2,j1,j2,k,t
f = file.open(name_file, "r")
while true do
local t = f:readline() if t == nil then break end
-- recherche de l'entête de version [print("\n ]
-- ATTENTION, il faut échapper la '(' avec un % et convertir le '\' en char(92)
k='print%("'..string.char(92)..'n '
i1,j1 = string.find(t,k)
if i1 ~= nil then
k=string.char(92)..'n"%)'
i2,j2 = string.find(t,k,j1)
z=name_file..": "..string.sub(t,j1+1,i2-2)
break
end
end
f:close()
uart.write(0,".")
end
return z
end
zdir={} list_files={}
local k,v = k,v local pfile = file.list()
for k,v in pairs(pfile) do
zdir[#zdir+1] = file_vers(k)
end
table.sort(zdir) for i=1, #zdir do print(zdir[i]) end
dir_vers=nil file_vers=nil list_files=nil zdir=nil
dir3=nil
end
dir3()
--[[
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,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 @@
-- programme pour faire un test depuis de le webide

View File

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

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