×

使用Twilio、Go和Arduino MKR GSM 1400远程播放MP3

消耗积分:0 | 格式:zip | 大小:0.57 MB | 2023-01-03

贾大林

分享资料个

描述

新的MKR 系列Arduino 板将改变快速原型设计物联网解决方案的格局。Arduino MKR GSM 1400对于希望使用蜂窝连接扩展其物联网项目范围的任何人来说都是一个很好的解决方案。通过将调制解调器与微控制器集成,一种新的一体式通信解决方案已经开始出现。这与Twilio 可编程无线 SIM相结合,可以使用机器对机器命令在全球范围内进行通信。“事物”现在可以通过 WiFi 或蓝牙以前无法实现的方式连接。

本教程演示了如何将机器到机器的命令从Arduino MKR GSM 1400发送到用 Go 编写的服务器。当服务器端接收到机器对机器命令时,音频文件将播放 .mp3 说“你好”。如果你想跳到前面,可以在 TwilioIoT GitHub 上找到已完成的项目

什么是 Arduino MKR GSM 1400?

Arduino MKR GSM 1400 是一款开发板,它使用u-blox SARAU201 调制解调器将Arduino Zero的功能与全球GSM连接相结合传统上,与调制解调器的通信是使用单独模块使用AT 命令完成的。该模型板附带一个库,可以通过函数调用更轻松地访问 AT 命令。

硬件要求

软件要求

设置 Twilio SIM

从包装中取出 Twilio SIM。接下来在 Twilio 控制台中注册并激活您的 SIM 。

软件方面的事情

在对硬件进行编程之前,我们需要安装一些软件才能使其正常工作。为了能够使用板载调制解调器发送 M2M 命令,我们需要MKRGSM库。

打开 Arduino IDE 并转到 Sketch > Manage Libraries。这是可以将 Arduino 和第 3 方库安装到 Arduino IDE 中的地方。

当库管理器窗口弹出时,搜索MKRGSM库并按安装。MKRGSM库将AT 命令包装到函数中,使其更容易与调制解调器通信。这是phonetabulous相信我。

安装库后,我们需要安装 Arduino MKR GSM 1400 板核。Arduino MKR GSM 1400 使用与使用AVR ATmega芯片组的传统 Arduino 不同的芯片组。该板使用SAMD21 Cortex-M0+ ,它需要一组不同的内核。Arduino IDE 不附带内核,计算机需要它们才能在连接时识别电路板。

在工具 > 开发板 > 开发板管理器下找到开发板管理器。

当 Board Manager 窗口出现时,搜索 Arduino SAMD Boards 并安装内核。  

重新启动 Arduino IDE 以完成安装。

伟大的!是时候继续进行硬件设置了。

硬件方面

要通过网络发送 M2M 命令,我们需要安装 Twilio SIM。从 Twilio SIM 卡中取出 Micro SIM

将 Twilio SIM 插入电路板下方的 SIM 插槽。

接下来,将 GSM 天线连接到板上。

使用 Micro-USB 电缆将电路板连接到计算机,您就可以连接到网络了。

创建 Arduino 草图

在 Arduino IDE 中创建一个新的 Arduino 草图(文件 > 新建)。提供了一个看起来像这样的模板。

void setup(){
}
void loop(){
}

为所有 GSM 函数实例化基类GSM 。要发送和接收 SMS 消息,还需要实例化GSM SMS类。这发生在 setup() 函数之前。

#include 
GSM gsmAccess;
GSM_SMS sms;

在 setup() 函数中创建波特率为115200 的串行连接。波特率决定了特定通信通道上的数据速度。

Serial.begin(115200);

使用gsmAccess.begin()函数连接到 Twilio SIM 上识别的蜂窝网络。

gsmAccess.begin();
Serial.println("GSM initialized");

在 loop() 函数中定义将使用beginSMS函数发送 M2M 命令的电话号码。我们将使用的数字是“ 2936 ”。这是一个特殊的 Twilio 短代码,保留用于在 Twilio SIM 之间交换 M2M 命令。它使用 SMS 传输通过蜂窝网络发送 M2M 命令。当 Twilio SIM 创建 M2M 命令时,会生成一个 Webhook,我们将很快讨论这个问题。

sms.beginSMS("2936");

将char 数组传递给函数sms.print()以创建要排队的新消息。

sms.print("hello world");
Serial.println(“Sending M2M Command”);

创建消息并排队后,使用endSMS()函数告诉调制解调器该过程已完成。一旦发生这种情况,将发送“hello world”消息。

sms.endSMS();
Serial.println("M2M Command Sent!");

最后一段代码是一个 while 循环,它将捕获程序并将其置于无限循环中。这样做的目的是确保 M2M 命令只发送一次。

while(1) {
    delay(4000);
}

完整的 Arduino 草图:

#include 
GSM gsmAccess;
GSM_SMS sms;
void setup(){
    Serial.begin(115200);
    gsmAccess.begin();
    Serial.println("GSM initialized");
}
void loop(){
    sms.beginSMS("2936");
        sms.print("hello world");
        Serial.println(“Sending M2M Command”);
       sms.endSMS();
       Serial.println("M2M Command Sent!");
       while(1) {
               delay(4000);
       }  
}

仔细检查是否已在“工具”>“电路板”下选择了电路板。如果未选中,编译器将在您尝试上传代码时抛出错误。

将新草图另存为“SayHelloArduinoGSM.ino”。在将新草图上传到电路板之前,让我们创建一个服务器来使用 Go 接收 M2M 命令。

使用 Go 和 Beep 启动音频响应服务器

使用下面的模板创建一个名为“SayHelloArduinoGSM.go”的新 Go 程序。

package main
import ( 
)
func main(){
}

接下来将以下库添加到导入部分。这是您将Beep等外部库链接到 Go 程序的地方。如果你还没有安装 Go,现在就使用Homebrew安装吧

package main
import (
        "fmt"
    "github.com/faiface/beep"
    "github.com/faiface/beep/mp3"
    "github.com/faiface/beep/speaker"
    "log"
    "net/http"
    "os"
    "time"
)

main函数中使用net/http库中HandleFunc()创建一个新的服务器路由。这将生成一个新的服务器端路由(“ /helloworld” ),用于从“2936”简码接收 M2M 命令。当收到 M2M 命令时,它将被传送到helloworld函数。在端口 9999 上使用ListenAndServe()函数打开一个端口并监听传入的连接。

func main(){
    http.HandleFunc("/helloworld", helloworld)
    http.ListenAndServe(":9999", nil)
}

极好的。现在我们必须创建helloworld函数。此函数接收到的 HTTP 请求将由http.Request类型表示。

func helloworld(w http.ResponseWriter, r *http.Request) {
}

当收到请求时,需要解析 M2M 命令。使用ParseForm()函数将请求正文解析为表单。

 if err := r.ParseForm(); err != nil {
        log.Printf("Error parsing form: %s", err)
        return
    }

可以使用PostFormValue()函数通过向其传递一个键来提取正文中的数据。该键将为您提供与 JSON 响应中命名组件关联的值。在这种情况下,我们正在寻找“Command”键的值。

 pwCommand := r.PostFormValue("Command")
    fmt.Println("pwCommand : ", pwCommand)

为了添加一点趣味,让我们在命令成功到达服务器时通过系统的音频播放一些哔声代码来播放音频文件。

 f, err := os.Open("helloworld.mp3")
    if err != nil {
        log.Fatal(err)
    }
    s, format, _ := mp3.Decode(f)
    speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10))
    playing := make(chan struct{})
    speaker.Play(beep.Seq(s, beep.Callback(func() {
        close(playing)
    })))
    <-playing

完整的 Go 程序:

package main
import (
    "fmt"
    "log"
    "net/http"
    "os"
    "time"
    "github.com/faiface/beep"
    "github.com/faiface/beep/mp3"
    "github.com/faiface/beep/speaker"
)
func main() {
    http.HandleFunc("/helloworld", helloworld)
    http.ListenAndServe(":9999", nil)
}
func helloworld(w http.ResponseWriter, r *http.Request) {
    if err := r.ParseForm(); err != nil {
        log.Printf("Error parsing form: %s", err)
        return
    }
    pwCommand := r.PostFormValue("Command")
    fmt.Println("incoming Command from Arduino MKR GSM 1400 : ", pwCommand)
    fmt.Println("Playing audio file!")
    f, err := os.Open("helloworld.mp3")
    if err != nil {
        log.Fatal(err)
    }
    s, format, _ := mp3.Decode(f)
    speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10))
    playing := make(chan struct{})
    speaker.Play(beep.Seq(s, beep.Callback(func() {
        close(playing)
    })))
    <-playing
}

启动服务器。

go run SayHelloArduinoGSM.go

使用 ngrok 构建桥梁

目前,硬件和软件部分单独存在。ngrok 将用于弥合差距。

当 SIM 向 Twilio 发送 M2M 命令时,Webhook 会发送到一个名为Commands Callback Url的用户定义的 url 我们将使用 ngrok 接收此 Webhook,然后将其路由到运行在我们自己机器上的服务器。要建立连接,请在服务器运行的同一端口上启动一个新的 ngrok 实例。

ngrok http 9999

复制使用 ngrok ( http://xxxxxxxx.ngrok.io )创建的转发url

在 Twilio 控制台中导航到Programmable Wireless 找到您之前在 SIM 下注册的SIM Configure选项卡下,您将找到Commands Callback Url 将 ngrok转发地址粘贴到文本框中,并将之前创建的服务器路由添加到 url 的末尾。

按保存。

通过天空发送消息

返回 Arduino IDE 并按上传。

上传后,仔细检查命令是否使用串行监视器正确发送。

  • 导航到工具 > 串行监视器

一旦从“2936”短代码发送了 M2M 命令,它就会被路由到 ngrok 并使用命令回调 Url进入 go 应用程序

最后 M2M 命令到达服务器和“helloworld.mp3”

细胞触觉!

继续连接东西

您刚刚使用魔法发送了您的第一个 M2M 命令。

此 M2M 命令模型是如何使用 Twilio 从远程硬件设备发送 M2M 命令的基础部分。Arduino MKR GSM 1400 具有集成的调制解调器和用于发送 AT 命令功能的软件,因此成为任何物联网原型设计套件的理想之选。

如果您有兴趣了解可以发送 M2M 命令的其他硬件,请查看无线机器到机器快速入门该项目以及其他项目可以在TwilioIoT GitHub 上找到

如有任何问题或好奇,请随时与我们联系。如果您有任何已经构建或正在计划构建的很酷的物联网项目,请给我留言。

作者

请启用 JavaScript 以查看

由 Disqus 提供支持的评论。


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !

'+ '

'+ '

'+ ''+ '
'+ ''+ ''+ '
'+ ''+ '' ); $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code ==5){ $(pop_this).attr('href',"/login/index.html"); return false } if(data.code == 2){ //跳转到VIP升级页面 window.location.href="//m.lene-v.com/vip/index?aid=" + webid return false } //是会员 if (data.code > 0) { $('body').append(htmlSetNormalDownload); var getWidth=$("#poplayer").width(); $("#poplayer").css("margin-left","-"+getWidth/2+"px"); $('#tips').html(data.msg) $('.download_confirm').click(function(){ $('#dialog').remove(); }) } else { var down_url = $('#vipdownload').attr('data-url'); isBindAnalysisForm(pop_this, down_url, 1) } }); }); //是否开通VIP $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code == 2 || data.code ==5){ //跳转到VIP升级页面 $('#vipdownload>span').text("开通VIP 免费下载") return false }else{ // 待续费 if(data.code == 3) { vipExpiredInfo.ifVipExpired = true vipExpiredInfo.vipExpiredDate = data.data.endoftime } $('#vipdownload .icon-vip-tips').remove() $('#vipdownload>span').text("VIP免积分下载") } }); }).on("click",".download_cancel",function(){ $('#dialog').remove(); }) var setWeixinShare={};//定义默认的微信分享信息,页面如果要自定义分享,直接更改此变量即可 if(window.navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger'){ var d={ title:'使用Twilio、Go和Arduino MKR GSM 1400远程播放MP3',//标题 desc:$('[name=description]').attr("content"), //描述 imgUrl:'https://'+location.host+'/static/images/ele-logo.png',// 分享图标,默认是logo link:'',//链接 type:'',// 分享类型,music、video或link,不填默认为link dataUrl:'',//如果type是music或video,则要提供数据链接,默认为空 success:'', // 用户确认分享后执行的回调函数 cancel:''// 用户取消分享后执行的回调函数 } setWeixinShare=$.extend(d,setWeixinShare); $.ajax({ url:"//www.lene-v.com/app/wechat/index.php?s=Home/ShareConfig/index", data:"share_url="+encodeURIComponent(location.href)+"&format=jsonp&domain=m", type:'get', dataType:'jsonp', success:function(res){ if(res.status!="successed"){ return false; } $.getScript('https://res.wx.qq.com/open/js/jweixin-1.0.0.js',function(result,status){ if(status!="success"){ return false; } var getWxCfg=res.data; wx.config({ //debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId:getWxCfg.appId, // 必填,公众号的唯一标识 timestamp:getWxCfg.timestamp, // 必填,生成签名的时间戳 nonceStr:getWxCfg.nonceStr, // 必填,生成签名的随机串 signature:getWxCfg.signature,// 必填,签名,见附录1 jsApiList:['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo','onMenuShareQZone'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function(){ //获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 wx.onMenuShareTimeline({ title: setWeixinShare.title, // 分享标题 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享给朋友”按钮点击状态及自定义分享内容接口 wx.onMenuShareAppMessage({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 type: setWeixinShare.type, // 分享类型,music、video或link,不填默认为link dataUrl: setWeixinShare.dataUrl, // 如果type是music或video,则要提供数据链接,默认为空 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ”按钮点击状态及自定义分享内容接口 wx.onMenuShareQQ({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口 wx.onMenuShareWeibo({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ空间”按钮点击状态及自定义分享内容接口 wx.onMenuShareQZone({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); }); }); } }); } function openX_ad(posterid, htmlid, width, height) { if ($(htmlid).length > 0) { var randomnumber = Math.random(); var now_url = encodeURIComponent(window.location.href); var ga = document.createElement('iframe'); ga.src = 'https://www1.elecfans.com/www/delivery/myafr.php?target=_blank&cb=' + randomnumber + '&zoneid=' + posterid+'&prefer='+now_url; ga.width = width; ga.height = height; ga.frameBorder = 0; ga.scrolling = 'no'; var s = $(htmlid).append(ga); } } openX_ad(828, '#berry-300', 300, 250);