Ameba Arduino: [RTL8195AM]让Ameba在Facebook涂鸦墙发表文章
DEPRECATED: 在Facebook GRAPH API v3.0(2018/05/01)发布之后,Facebook APP代表使用者发表文章的功能已经不再支持
Facebook是线上社群网站,提供平台给一般使用者,使用者可以在上面沟通、分享、储存影音、参与社团等等,并且提供Graph API供开发者开发应用程式在不同的平台上,包括iOS、 Android、网页应用程式、与Facebook Canvas。应用程式可以在使用者同意之下,使用使用者的资源与服务。
Graph API是基于HTTP protocol的API,在这篇文章里将会使用Graph API让Ameba在涂鸦墙上发表文章
材料准备
- Ameba x 1
范例说明
- 设定Facebook应用
为了让Ameba可以存取Facebook,Facebook需要知道来存取的用户是谁,以及是哪个应用程式的要求。所以我们需要先为我们的应用程式作一些设定。首先到这个网址 https://developers.facebook.com/apps
如果是第一次使用, 会出现成为开发人员的选项, 点选注册
跳出一张选单填选工作职称,以及同意Facebook的Policy,完成后点选Register。
成功后点选点选Done
如果之前没有开发过任何Facebook应用程式, 会跳出底下选单让你选。这边我们选Website
点选右上方的 “Skip and Create App ID”
跳出一张表单,要填写以下内容
- Display Name: 这个名字会是你在后台管理时看到的名字,也是这个应用程式代表使用者在Facebook上做出任何行为时会看到的名字。这个范例里我们填ameba
- Contact Email: 如果你已经登入,这边应该已经帮你填好了
- Category: 根据你的应用填分类
填完之后点选 “Create App ID”
完成后会进入后台管理平台。画面上方有个 APP ID,这个 APP ID用来识别你目前的Facebook应用程式,范例里的APP ID是 “312698492463829”。应用程式后端管理平台可以做一些额外的设定,像是OAuth、应用程式domain、上架流程等等
- 取得Access Token
Facebook应用程式会代表使用者在Facebook操作,如果让应用程式拥有所有的权限就太危险了,所以应用程式实际上需要一个access token。 access token是一组很长的字串,在Graph API里所使用的HTTP protocol常常需要携带这个access token,而Facebook纪录了每一个access token所拥有的权限,代表的应用程式,以及时间限制。我们可以在Graph API Explorer管理我们的access token: https://developers.facebook.com/tools/explorer
这个后台管理介面好几个部份,简述如下:
- 右上方有个Application的选单,第一次进来应该会选到 “Graph API Explorer”, 我们点开这个选单应该会看到里面有 ameba的应用程式
- Application的选单下方有个 “Get Token”的选单, 点选之后里面有三种Token,这个范例里我们只会用到 “user access token”,关于不同的access token的用途可以参考底下网址:
https://developers.facebook.com/docs/facebook-login/access-tokens - 在 “Token Type”左边则是Token的值,以字串表示
- 下面那栏则是使用者想要下达的Graph API命令。由左至右分别是
- HTTP Request type: 根据Graph API使用手册填入想下达的HTTP Request type,常用的通常只有GET与POST
- Graph API Version: Facebook会不同时改版Graph API,范例里的版本是v2.8。在应用程式开发里也可以不带版号,Facebook预设会使用当下所允许的最旧版本
- Request content: 这里填Graph API里需要带的参数。 Graph API Explorer会视情况帮你加上access token
- 画面中央则是一些debug讯息
现在我们来设定应用程式的access token,点选Application,选择ameba
在 “Get Token” 的地方,点选 “Get User Access Token”
接着会跳出一个选单,这个选单是让你勾选你的 ameba Facebook应用程式可以代表使用者作哪些行为。因为我们需要在涂鸦墙上写东西,所以我们参考Graph API说明文件:
https://developers.facebook.com/docs/graph-api/reference/v2.8/group/feed
https://developers.facebook.com/docs/graph-api/reference/v2.8/user/feed
于是我们需要底下几个permission:
publish_actions, user_managed_groups
接着可能会出现警告讯息,这是因为Facebook不希望使用者在不知情的情况下被应用程式拿来散布与发表讯息,因此要求应用程式提供相关Policy供使用者确认,这一步我们先跳过,只有要将应用程式公开并尝试通过Facebook审查才需要补上这部份。
接着会询问你是否同意ameba Facebook应用程式将代替你发表文章,点选OK
接着询问你是否同意ameba Facebook应用程式将代替你管理社团与粉丝团,点选OK
完成后跳回Graph API Explorer,现在access token的地方已有值
我们先利用Graph API Explorer测试一下是否可以发文, 我们在HTTP request的几个栏位填写如下:
- HTTP REQ Type: 点选并改成POST
- HTTP REQ content: 填写 “me/feed?message=HelloWorld” 其中message后面的值是要发表的内容,以URI编码
完成后按下Submit后,下方debug资讯会出现该篇文章的id
文章的id可以拿做一些操作,像是修改文章、按赞、留言等等,这些可以在Graph API文件里找到相关资讯。
我们回到Facebook,会发现自己的涂鸦墙上,ameba Facebook应用程式已经代替自己发表了文章,并且该篇文章自己名字底下有 “ameba” 的字串
刚刚执行的动作其实是送HTTP protocol的资讯,并且可以用openssl来模拟,如果你有安装openssl的话,请执行:
openssl s_client -connect graph.facebook.com:443
会进入interactive mode,接着输入底下内容(中间请勿打错字修改删除,这些行为都会被当成控制字元送出)。其中access_token=后面的值是你的access token。最后的message=我们改成HelloWorldV2。最后面记得输入空白行结束HTTP命令
POST /v2.8/me/feed?access_token=EAAEcZAcqQqtUBAAN0YbAemjZCwvmknqjocENiPwUX92TR7Q54jiKrtyEOR8p2EgfR1RQz3uWeDmEQt9oNYOMaRBqGci55CD9chdXcCQXu1jwXPvLpvPZAMeZBVxWZA94sCEZBVN93ZADDe6XkaJpDxJlvdTF0zATFMZD&message=HelloWorldV2 Host: graph.facebook.com
成功的话应该会收到底下讯息
HTTP/1.1 200 OK Access-Control-Allow-Origin: * Pragma: no-cache Cache-Control: private, no-cache, no-store, must-revalidate facebook-api-version: v2.8 Expires: Sat, 01 Jan 2000 00:00:00 GMT Content-Type: text/javascript; charset=UTF-8 x-fb-trace-id: AWAKUnVL1yX x-fb-rev: 2757773 Vary: Accept-Encoding X-FB-Debug: 7SqJtuZjt0RZzpAGiknOhcUs0qbDG0Q4WNep592ssnzoc0xRM7IGhsrGy/B38uvGt36vky8rgcfVTD8zuLQ7NA== Date: Mon, 26 Dec 2016 11:42:36 GMT Connection: close Content-Length: 40 {"id":"103964610106403_103999236769607"}closed
涂鸦墙上也多了一篇文章
如果想在message带空格或是中文,可以参考一些http url encoder将中文改成URL的值 http://meyerweb.com/eric/tools/dencoder/
这部份留给读者自行尝试
- 检视token的内容与展延token
我们在前小节里取得的access token其实有时间限制,我们可以使用 Access Token Debugger 来检查何时到期
https://developers.facebook.com/tools/debug/accesstoken/
可以看到这个access token的资讯,包括是哪个应用程式所使用、权限、到期时间(以UNIX epoch时间表示)。通常预设Graph API Explorer给的access token是short-lived token,时间在两个小时内就到期。 Access token还有另一种long-lived token,时间为两个月到期,并且每次使用token就可以展延为两个月。在Access Token Debugger下方就有Extend Access Token的选项,我们点选它
下方会出现新的Token,这个long-lived token的值与short-lived token的值不同,我们点选右下方的 Debug看这个 long-lived token的内容
会看到它的时间已经展延成两个月
最后补上几点说明:
1. 根据Graph API文件,每次使用token,Facebook会在不固定的时间重置long-lived token 为2个月,所以只要应用程式一直有在使用,就不用担心过期的问题
https://developers.facebook.com/docs/facebook-login/access-tokens/expiration-and-extension
但如果一直都没使用并且token到期,就得重新执行索取token的动作,新的token的值不会与旧的相同
2. 我们可以不经由Graph API explorer取得short-lived token或long-lived token。细节可以参考Graph API文件 https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow
- 在社团或粉丝团涂鸦墙发表文章
这部份其实跟在自己涂鸭墙发表文章很像,只是我们需要社团的group id。进入社团页面之后,可以在网址列上看到社团的group id,以底下的例子来说是 “1210426395661463”
如果社团或粉丝团曾经修改过名称,可以藉由一些网站来帮忙找group id:
http://wallflux.com/facebook_id/
接着我们使用 Graph API Explorer填入以下的值
- HTTP REQ type: 一样是 POST
- HTTP REQ content: “1210426395661463/feed?message=HelloGroup”
前面那串数字是group id,后面的message我们改成HelloGroup
接着按下Submit,成功的话一样会在Debug资讯栏出现该篇文章的id
回到社团页面,会看到ameba已代替使用者成功发表文章
范例一:使用Ameba在涂鸦墙上发表文章
要让Ameba在Facebook涂鸦墙发表文章,做的事情与前面使用openssl模拟发文的行为类似,只需经由SSL传送HTTP protocol的内容即可。
在这个范例里我们每分钟发表一篇文章,因为Facebook会审查我们是否发表同样的文章内容,所以我们用字串阵列来改变每次发表的内容。在Arduino IDE上打开范例 “File” -> “Examples” -> “AmebaWiFi” -> “Facebook” -> “facebook_feed_publish”
填上你欲连上的WiFi AP资讯
填上你所使用的access token
设定涂鸦墙的对象,如果是自己的涂鸦墙则使用 “me”,如果是社团或粉丝团则使用并填上group id
编译并上传至Ameba执行,等待一会儿可以看到Ameba在代表使用者发表文章
范例一:程式码说明
- 变数说明
字串 server内容为Facebook Graph API的server位置
char server[] = "graph.facebook.com"; // facebook graph api service
字串 access_token里面放的是short-lived token或long-lived token。如果是short-lived token要注意token是否过期,一般来说short-lived token的期限大约在2小时
char access_token[] = "EAAEcZAcqQqtUBAAN0YbAemjZCwvmknqjocENiPwUX92TR7Q54jiKrtyEOR8p2EgfR1RQz3uWeDmEQt9oNYOMaRBqGci55CD9chdXcCQXu1jwXPvLpvPZAMeZBVxWZA94sCEZBVN93ZADDe6XkaJpDxJlvdTF0zATFMZD";
范例里我们会使用到SSL,所以宣告WiFiSSLClient的变数
WiFiSSLClient client;
字串阵列message_list里面放的是我们想发布的讯息,以URI的方式encode。网路上有很多URI encode的工具可以帮忙转换特殊符号与特殊文字
#define MESSAGE_LIST_SIZE 5 int message_index = 0; char *message_list[MESSAGE_LIST_SIZE] = { ……
- 程式流程
程式流程图如下
比较需要注意的是当我们用WiFiSSLClient送HTTP POST讯息给Graph API之后,需要确认server端回应的讯息,如果没有成功发布讯息至图鸦墙,那么server会回一些简易的错误资讯供你参考
范例二:使用Ameba发布PM2.5讯息至涂鸦墙上
这个范例里我们会使用Plantower的PMS3003/PMS5003模组,这个模组可以侦测空气中的细微粒子,并给出PM2.5指数,有关Plantower的使用可以参考网站上之前的文章。
范例里我们结合PM2.5,让Ameba发布侦测到的PM2.5讯息。当PM2.5的值变化超过10,或是已经一小时没有发布讯息,那么Ameba就会发布目前的PM2.5数值与注意事项至涂鸦墙
我们打开范例“File” -> “Examples” -> “AmebaWiFi” -> “Facebook” -> “facebook_pm25_notifier”
填上你欲连上的WiFi AP资讯:
填上你所使用的access token
设定涂鸦墙的对象,如果是自己的涂鸦墙则使用 “me”,如果是社团或粉丝团则使用并填上group id
选择欲发布讯息的语言,预设是英文,可以选择繁体中文
设定完成后,将PMS3003或PMS5003接上Ameba:
然后将程式码编译并上传至Ameba,执行结果如下,可以看到Ameba每隔一段时间就更新PM2.5数据,并提供户外活动建议
范例二:程式码说明
这个范例与前一个范例 “facebook_feed_publish” 类似,除了PM2.5的部份
PM2.5的部份,我们使用类别PMS3003来帮忙取得PMS3003/PMS5003的PM2.5数值。所使用的是pin 0与pin 1的uart功能
PMS3003 pms(0, 1);
然后呼叫get_pm25_aircondition()取得PM2.5的值, 里面调用 get_pm2p5_air() 取得PM2.5数值
int pm25 = pms.get_pm2p5_air();
并且使用moving average来避免数值突然不稳定的情况, 公式如下:
PM2.5avg = PM2.5avg * 0.9 + PM2.5now * 0.1
在 get_pm25_level()里面,根据底下的PM2.5分类方式与建议做分类
http://taqm.epa.gov.tw/taqm/en/fpmi.aspx
http://taqm.epa.gov.tw/taqm/tw/fpmi.aspx
整理程式流程如下: