|
前言
之前试了微信点灯,觉得可以做个微信相册试试。
步骤
1. 材料准备:树莓派,显示屏
2. 找个外壳,又是个纸盒,把手机牌子挡住
3. 确定位置
4. 切割
5. 安装屏
6. 找个礼品包装纸来装饰下更好看
7. 包装好
8. 然后,把驱动和树莓派往盒里塞的时候,悲剧了……我,我,我去年买了个屏……屏线断了
9. 好吧,先不管屏了。服务端写好,找个服务器部署一下吧。外面有免费试用的服务器大家可以申请试用。我就拿另一个树莓派来当服务器,只是做实验嘛。自己家中的网络还需要做内网穿透,网上能找到不少,这里就不打广告了。
安装好 LAMP 环境后,把服务端程序放到 html 目录就好了(以后有空改成服务比较适合)。
10. 公众号配置指向我们的服务器地址,首先要先用官网的 valid 示例来让公众号配置通过验证,然后再改为自己的程序。具体操作网上很多教程了,就不多啰嗦啦
11. 客户端程序也上传到客户端的树莓派上
12. 这是客户端
13. 这是服务器[捂脸]
14. 小显示屏坏了,我还有大的呢,嘿嘿!
看看全家福:电视上面的 pi 是服务器,下面的 pi 是客户端,手机端的微信,最重要的最后说,大显示屏!
15. 手机上传照片到公众号
16. 大屏幕的微信相册开始显示啦!
代码
服务端主程序
[mw_shl_code=php,true]
<?php
// ----------------------------------------------------------------------------
// wxAlbum.php
//
// Created 2017-10-12
// By seesea <seesea2517#gmail#com>
//
// 微信相框服务端
// 时间仓促,只做演示用,待完善的功能:
// 1. 用户绑定、解绑、查询相册
// 2. 用户照片管理功能
// 3. 相册内置 id,启动时显示 id 及二维码(不过个人公众号未开放扫码功能,可以用扫码得到 id 内容后粘贴发文本的方式来绑定)
// 4. 用户、相册、照片的数据库管理
// ----------------------------------------------------------------------------
//define your token
define("TOKEN", "seesea");
define("DIR_PHOTO", "/var/www/html/album");
define("LOG_FILE", "/var/www/html/log.txt");
define("MSG_INVALID_TYPE", "无效的消息类型,仅接收文本和图片。");
define("MSG_NO_COMMAND", "未输入命令。");
define("MSG_INVALID_SERIAL_NUM", "无效的序列号。");
define("MSG_HELP", "帮助:\n上传:直接发图\n绑定:发送文本“绑定 序列号”\n解绑:发送文本“解绑 序列号/序号”,直接发送“解绑”会列出所有已绑定的相框序列号并标记序号\n全部解绑:发送文本“解绑全部”");
function logMsg($logText)
{
file_put_contents(LOG_FILE, $logText . "\n", FILE_APPEND);
}
function downloadFile($url, $newName)
{
$content = file_get_contents($url);
file_put_contents($newName, $content);
}
logMsg("\n\nstart....\n");
$wechatObj = new wxAlbum();
$wechatObj->processMessage();
class wxAlbum
{
private $xmlMsgObj;
private $fromUsername;
private $toUsername;
private $msgType;
public function __construct()
{
$dirs = array(DIR_PHOTO);
foreach($dirs as $dir)
{
if (! file_exists($dir))
{
mkdir($dir);
}
}
}
public function valid()
{
$echoStr = $_GET["echostr"];
//valid signature , option
if($this->checkSignature())
{
echo $echoStr;
exit;
}
}
public function processMessage()
{
//get post data, May be due to the different environments
$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
logMsg($postStr);
if (empty($postStr))
{
echo ""; // 回复 "success" 或空 ""
exit;
}
/* libxml_disable_entity_loader is to prevent XML eXternal Entity Injection,
the best way is to check the validity of xml by yourself */
libxml_disable_entity_loader(true);
$this->xmlMsgObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
$this->fromUsername = $this->xmlMsgObj->FromUserName;
$this->toUsername = $this->xmlMsgObj->ToUserName;
$this->msgType = $this->xmlMsgObj->MsgType;
switch ($this->msgType)
{
case "image":
$this->processImageMessage();
break;
case "text":
$this->processTextMessage();
break;
default:
$this->responseUserByText(MSG_INVALID_TYPE);
};
}
private function responseUserByText($msg)
{
$time = time();
$msgType = "text";
$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Content><![CDATA[%s]]></Content>
<FuncFlag>0</FuncFlag>
</xml>";
$reponseXML = sprintf($textTpl, $this->fromUsername, $this->toUsername, $time, $msgType, $msg);
echo $reponseXML;
}
private function processImageMessage()
{
$picUrl = $this->xmlMsgObj->icUrl;
$filePathName = DIR_PHOTO . "/" . $this->xmlMsgObj->MsgId;
downloadFile($picUrl, $filePathName);
// 调试用 $this->responseUserByText("Down file: " . $filePathName);
$this->responseUserByText("已上传服务器,文件名: " . $this->xmlMsgObj->MsgId);
}
private function processTextMessage($xmlMsgObj)
{
$keyword = trim($this->xmlMsgObj->Content);
if (empty($keyword))
{
$this->responseUserByText(MSG_NO_COMMAND);
}
$contentStr = "收到命令:" . $keyword;
$this->responseUserByText($contentStr);
}
private function showHelp()
{
$this->responseUserByText(MSG_HELP);
}
private function checkSignature()
{
// you must define TOKEN by yourself
if (!defined("TOKEN"))
{
throw new Exception('TOKEN is not defined!');
}
$signature = $_GET["signature"];
$timestamp = $_GET["timestamp"];
$nonce = $_GET["nonce"];
$token = TOKEN;
$tmpArr = array($token, $timestamp, $nonce);
// use SORT_STRING rule
sort($tmpArr, SORT_STRING);
$tmpStr = implode( $tmpArr );
$tmpStr = sha1( $tmpStr );
logMsg($tmpStr);
if( $tmpStr == $signature )
{
return true;
}else{
return false;
}
}
}
?>
[/mw_shl_code]
服务端辅助程序:查询相册服务端的照片数
[mw_shl_code=php,true]<?php
// ----------------------------------------------------------------------------
// countPhotos.php
//
// Created 2017-10-21
// By seesea <seesea2517#gmail#com>
//
// 计算服务端相应相册 id 的照片
// 简单演示用,以后有空完善根据相册 ID 来获取该相册的相片数
// ----------------------------------------------------------------------------
echo (count(scandir("/var/www/html/album")) - 2)
?>
[/mw_shl_code]
服务端辅助程序:列出相册服务端的照片名
[mw_shl_code=php,true]<?php
// ----------------------------------------------------------------------------
// countPhotos.php
//
// Created 2017-10-21
// By seesea <seesea2517#gmail#com>
//
// 列出服务端相应相册 id 的照片
// 简单演示用,以后有空完善根据相册 ID 来获取该相册的相片
// ----------------------------------------------------------------------------
echo (implode(" ", array_diff(scandir("/var/www/html/album"), array(".", ".."))))
?>
[/mw_shl_code]
客户端脚本
[mw_shl_code=bash,true]#!/bin/bash
# ----------------------------------------------------------------------------
# startAlbum.sh
#
# Created 2017-10-20
# By seesea <seesea2517#gmail#com>
#
# 相册客户端
# ----------------------------------------------------------------------------
PIC_DIR=pics
HTTP_SERVER="http://你的服务器地址"
COUNT_PHOTO_URL="$HTTP_SERVER/countPhotos.php"
LIST_PHOTO_URL="$HTTP_SERVER/listPhotos.php"
DOWN_PHOTO_URL="$HTTP_SERVER/album"
# QIV_COMMAND="qiv -smfD -d1 $(ls -r $PIC_DIR/*) --display :0"
mkdir $PIC_DIR 2>/dev/null
# bash -c "$QIV_COMMAND" &
# $QIV_COMMAND &
qiv -smfiD -d1 $(ls -r $PIC_DIR/* 2>/dev/null) --display :0 >/dev/null &
qiv_pid=$!
while true
do
local_photo_count=$(ls $PIC_DIR | wc -l)
remote_photo_count=$(curl "$COUNT_PHOTO_URL" 2>/dev/null)
if (( local_photo_count < remote_photo_count ))
then
all_photo_list=$(curl "$LIST_PHOTO_URL" 2>/dev/null)
local_photo_list=$(ls -1 $PIC_DIR)
if [ -z "$local_photo_list" ]
then
local_photo_list="xxxxxxxxxxx"
fi
for name in $(echo -e "${all_photo_list// /\\n}" | grep -vE "$local_photo_list")
do
wget -q -P$PIC_DIR "$DOWN_PHOTO_URL/$name"
done
kill $qiv_pid
qiv -smfiD -d1 $(ls -r $PIC_DIR/* 2>/dev/null) --display :0 >/dev/null &
qiv_pid=$!
fi
sleep 1; # 测试用的间隔短一些,方便更快看到结果
done[/mw_shl_code]
视频
|
|