草庐IT

ESP8266 阿里云 MQTT物联网测试

五块钱的方便面 2023-09-02 原文

 前面写了篇恢复ESP8266 发布APRS的文章

ESP8266 APRS 板子修改为提交数据到T2服务器的方法_五块钱的方便面的博客-CSDN博客一年多前,我折腾好了基于ESP8266 + BMP280 + 锂电池 方案做了个nodeMCU固件的APRS WX板子。https://github.com/bg6cq/nodemcu_bme280https://github.com/bg6cq/nodemcu_bme280自己动手编译nodemcu固件(ESP8266)_五块钱的方便面的博客-CSDN博客_nodemcu 固件编译起因或者说好处最近在玩ESP8266 + BMP280 的APRS气象数据报,其实很早之前就看到过BG6CQ老师的gihttps://blog.csdn.net/chenqioulin/article/details/124424242这两天有空,正好把MQTT的也玩玩,大名鼎鼎的物联网,首选肯定是阿里云了,对我这种玩具型的免费,而且服务端稳定。

nodeMCU的固件当时是编译进了MQTT支持的,BG6CQ老师的程序代码里面也同时写了MQTT的部分,不过不是针对阿里云,需要修改。

先说下结论:如果不是有大量的代码而使用他人的程序,真不如自己写了(lua上手程度真的和arduino没啥区别了),改了几天下来,逻辑改的乱七八糟,居然也能正常工作,真是神奇。

阿里云有好多SDK之类,我没用,还是用的nodeMCU 的Lua来改,毕竟有现成的代码。

还是做个笔记吧

1.阿里云部分

云端部分网上有很多现成的文章,但是都写的过于复杂,我自己简单整理了下:

开通物联网--》新建产品--》添加设备。  

个人理解:产品代表一个完整产品,设备代表产品上的小的功能模块,但是模块的功能定义或者说数据模型(就是传感器的温度气压电压这些)是在产品里面定义的。

创建好这几个以后,mqtt连接参数直接在设备的信息里面有个MQTT连接参数,并不需要网上那些文章说的还要单独去做什么计算。

2.软件测试

创建好后不要直接去设备上改代码测试,下载MQTTX这个软件,垮平台的,UOS上用完全没问题。

MQTTX添加个连接,几个参数第一步说了设备信息里面有现成的了。

 点链接后,可以直接订阅个topic,topic其实相当于一个消息通道,客户端订阅后,服务器下发消息,客户端就会收到。

服务器的topic在产品的topic类列可以看到,已经有很多现成的topic了,也可以自定义topic,我只想通过服务器获取esp8266上报的温度气压电压等信息,所以客户端不需要订阅,但这里为了获取8266要push的json报文格式,所以选下面的属性设置 订阅一个。

订阅后在设备的调试界面,对产品定义的几个属性做设置,这时候MQTTX应该能收到服务器下发的topic信息,这样就能得到报文的json格式,属性的标识符见产品的功能定义,这里面还可以对产品属性做修改。比如标识符,数据类型,取值范围,布进。除了里面默认有的,还可以自定义功能。

 3.设备端代码

设备商代码主要就是:

mqtt客户端创建-》mqtt连接-》mqtt publish(包含温度气压等)-》mqtt:close

3.1 mqtt 客户端创建及连接到服务器

function mqtt_connect()
  m = mqtt.Client(mqtt_client_id,30,mqtt_user,mqtt_password)
  print(mqtt_client_id)
-- resolv ali iot host ip
sk = net.createConnection(net.TCP, 0)
net.dns.setdnsserver("114.114.114.114", 0)
net.dns.resolve(mqtt_host_dns, function(sk, ip) mqtt_host=ip end)
print("resolved mqtt_host:"..mqtt_host.."\n") 
sk = nil


print("begin connect mqtt,mqtt_host:"..mqtt_host.."!")
m:connect(mqtt_host, mqtt_port, false,function(m) mqtt_connected = true print("mqtt online") end,
function(m,reason) print("fail with:"..reason) end)
end

3.2 mqtt  publish

if count%2 == 0 then
  if mqtt_connected then
  
    print("mqtt publish") 
-- publish to ali iot server
    humi_ali=string.format("%.1f",humi)
    temp_ali=string.format("%.1f",temp)
    press_ali=string.format("%.1f",press)
    voltage_ali=string.format("%.2f",Voltage)
    mqttstr="{\"method\":\"thing.service.property.set\",\"id\":\"1540317865\",\"params\":{\"CurrentHumidity\":"..humi_ali..",\"CurrentTemperature\":"..temp_ali..",\"Atmosphere\":"..press_ali..",\"WiFiRSSI\":"..rssi..",\"CurrentVoltage\":"..voltage_ali..
 "},\"version\":\"1.0.0\"}"
    print("str is:"..mqttstr)
    m:publish(mqtt_topic,mqttstr,0,0)
    data_send = true
    m:close()
  elseif send_mqtt then
      mqtt_connect()
      m:on("offline", function(c)
      print("mqtt offline, try connect to "..mqtt_host..":"..mqtt_port)
      mqtt_connected = false
    end)  
  end
 send_data()  
end

这个里面send_data()主要发送的APRS数据,写这一段是纠结的不行,BG6CQ老师原来的代码写了发送aprs mqtt http三类,想删吧又怕搞乱了,不删吧这些逻辑看起来头晕,凑合用吧。

主要就是mqttstr的连接,然后发送完关闭mqtt连接,这个Lua里面的回调函数(函数执行成功后可以将返回的数

据用来做新写的函数参数并在函数执行成功后执行)真是不习惯啊。比如:

sk = net.createConnection(net.TCP, 0)
net.dns.setdnsserver("114.114.114.114", 0)


net.dns.resolve(mqtt_host_dns, 
--下面2行就是net.dns.resolve这个函数的回调函数,function(sk, ip) 是函数头,
-- 就一个语句mqtt_host=ip 然后加上 end表示这个回调函数结束,end后面的)是net.dns.resolve这个函数的括号

function(sk, ip) 
mqtt_host=ip end)

半吊子改程序就是慢啊,上传后在esp8266上调试也费时间。

调试成功后,上阿里云管理界面可以选调试,能实时收到客户端传上来的报文。

最后在设备的物模型数据里面可以看到我们产品里面定义的属性,值就是我们ESP8266报上来的数据 

据说可以微信小程序来查看这些数据。接下来搞一个玩完,至于设备端订阅topic,目前我还没想到有需要esp8266控制的,所以目前暂时不搞,要做成好用的,那就可以订阅下topic,通过mqtt做代码更新等等,反正官方都给你定义好了那么多topic。

微信小程序未完待续~

有关ESP8266 阿里云 MQTT物联网测试的更多相关文章

  1. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  2. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  3. ruby - Ruby 的 Hash 在比较键时使用哪种相等性测试? - 2

    我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。

  4. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

  5. ruby - Sinatra:运行 rspec 测试时记录噪音 - 2

    Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/

  6. ruby-on-rails - 迷你测试错误 : "NameError: uninitialized constant" - 2

    我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test

  7. ruby - 即使失败也继续进行多主机测试 - 2

    我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r

  8. ruby-on-rails - 如何使辅助方法在 Rails 集成测试中可用? - 2

    我在app/helpers/sessions_helper.rb中有一个帮助程序文件,其中包含一个方法my_preference,它返回当前登录用户的首选项。我想在集成测试中访问该方法。例如,这样我就可以在测试中使用getuser_path(my_preference)。在其他帖子中,我读到这可以通过在测试文件中包含requiresessions_helper来实现,但我仍然收到错误NameError:undefinedlocalvariableormethod'my_preference'.我做错了什么?require'test_helper'require'sessions_hel

  9. ruby-on-rails - Cucumber 是否只是 rspec 的包装器以帮助将测试组织成功能? - 2

    只是想确保我理解了事情。据我目前收集到的信息,Cucumber只是一个“包装器”,或者是一种通过将事物分类为功能和步骤来组织测试的好方法,其中实际的单元测试处于步骤阶段。它允许您根据事物的工作方式组织您的测试。对吗? 最佳答案 有点。它是一种组织测试的方式,但不仅如此。它的行为就像最初的Rails集成测试一样,但更易于使用。这里最大的好处是您的session在整个Scenario中保持透明。关于Cucumber的另一件事是您(应该)从使用您的代码的浏览器或客户端的角度进行测试。如果您愿意,您可以使用步骤来构建对象和设置状态,但通常您

  10. ruby-on-rails - 如何调试 cucumber 测试? - 2

    我有:When/^(?:|I)follow"([^"]*)"(?:within"([^"]*)")?$/do|link,selector|with_scope(selector)doclick_link(link)endend我打电话的地方:Background:GivenIamanexistingadminuserWhenIfollow"CLIENTS"我的HTML是这样的:CLIENTS我一直收到这个错误:.F-.F--U-----U(::)failedsteps(::)nolinkwithtitle,idortext'CLIENTS'found(Capybara::Element

随机推荐