【转载】java 时间戳跟PHP时间戳的转换

java 时间戳和PHP时间戳 的转换

原文地址:http://www.myexception.cn/php/1032678.html
总结一下java 时间戳和PHP时间戳 的转换问题:
由于精度不同,导致长度不一致,直接转换错误。
JAVA时间戳长度是13位,如:1294890876859
PHP时间戳长度是10位, 如:1294890859

主要最后三位的不同,JAVA时间戳在PHP中使用,去掉后三位,如:1294890876859-> 1294890876 结果:2011-01-13 11:54:36
echo date(‘Y-m-d H:i:s’,’1294890876′);
PHP时间戳在JAVA中使用,最后加三位,用000补充,如:1294890859->1294890859000
结果:2011-01-13 11:54:19
SimpleDateFormat df = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);
String dateTime = df.format(1294890859000L);
System.out.println(df);

树莓派充当mp3播放器

最近想着通过Raspberry Pi来充当mp3用,因为没有显示器,只有音箱,所以就把音箱直接接在Pi的3.5mm耳机接口上。可以在电脑上或者手机上通过网页来播放音乐。也许有人问,有了电脑或手机为什么要这个,因为也许电脑、手机的外放效果不怎么样,接音箱总归好一些。而且对于我这个懒人,就喜欢躺床上,希望通过手机来控制一切,所以才诞生了这个想法。

基本步骤:

1.安装系统,本人使用的是xbian,理论上其他系统也可以。如果已经装好系统,可以跳过这一步

2.安装mpg123

命令: apt-get install mpg123

安装完毕mpg123,拷贝一个mp3文件到Pi中,可以运行mpg123 xxx.mp3(xxx.mp3为mp3文件名)看看能否正常运行。

本人在运行的时候出现找不到输出口的问题,大概是声卡驱动没有正确加载,运行以下命令解决:

sudo modprobe snd-bcm2835

3.安装lnmp,其实这里只需要安装nginx和php就可以了。

参照我之前的帖子 https://blog.wo.ai/archives/194 来进行安装

或者简单运行如下程序:

apt-get install nginx php5 php5-fpm php5-mysql php5-curl php5-gd php5-intl php-pear php5-imagick php5-imap php5-mcrypt php5-memcache php5-ming php5-ps
php5-pspell php5-recode php5-snmp php5-sqlite php5-tidy php5-xmlrpc php5-xsl

4.然后配置php sudo权限,这样php执行命令的时候不需要输入自己的密码

为 nginx,而想透过 PHP 发送irsend,用 root 输入指令 vi /etc/sudoers,
在档案最底加上以下一行:

www-data ALL=NOPASSWD: /usr/bin/mpg123

5.开始php旅程:

首先是index.php,用来遍历某个目录下所有的mp3文件,并显示出来:

//获取文件目录列表,该方法返回数组
function getDir($dir) {
$dirArray[]=NULL;
if (false != ($handle = opendir ( $dir ))) {
$i=0;
while ( false !== ($file = readdir ( $handle )) ) {
//去掉””.”、”..”以及带”.xxx”后缀的文件
if ($file != “.” && $file != “..”&&!strpos($file,”.”)) {
$dirArray[$i]=$file;
$i++;
}
}
//关闭句柄
closedir ( $handle );
}
return $dirArray;
}

//获取文件列表
function getFile($dir) {
$fileArray[]=NULL;
if (false != ($handle = opendir ( $dir ))) {
$i=0;
while ( false !== ($file = readdir ( $handle )) ) {
//去掉””.”、”..”以及带”.xxx”后缀的文件
if ($file != “.” && $file != “..”&&strpos($file,”.mp3″)) {
$fileArray[$i]=”/home/test/”.$file;
if($i==100){
break;
}
$i++;
}
}
//关闭句柄
closedir ( $handle );
}
return $fileArray;
}

读取mp3tag

function readmp3($mp3_file)
{
$fp=fopen($mp3_file,"rb"); //读取mp3文件
//首先判断是否有TAG,如果没有,那就没必要读取了,方法就是读取倒数128-126字节,看是否是TAG
//详情参看http://www.readlog.cn/archives/2961/
fseek($fp,-128,SEEK_END); //指针移到倒数128字节处
$tag=fread($fp,3); //读取倒数128-126字节位置的数据
if($tag=="TAG") //如果这3个字节是TAG,表明有TAG
{
$mp3=array();
//标题30个字节,从倒数125字节到倒数96字节
//现在直接读就可以了
$mp3['标题']=fread($fp,30);
//艺术家30个字节,从倒数95字节到66字节
$mp3['艺术家']=fread($fp,30);
//专辑30个字节,从倒数65字节到36字节
$mp3['专辑']=fread($fp,30);
//年份4个字节,从倒数35字节到32字节
$mp3['年份']=fread($fp,4);
//注释28个字节,从倒数31字节到4字节 (有的是30个字节,那就把倒数第2,3位归入注释了)
$mp3['注释']=fread($fp,28);
fseek($fp,1,SEEK_CUR); //跳过倒数第3位保留位
//第几首1个字节,倒数第2位
$mp3['编号']=ord(fread($fp,1));
//流派1个字节,就是倒数第一个字节了
//流派这里是存放的整型数据,可以写个函数来把数字变成具体的文字。
//具体含义参看http://www.readlog.cn/archives/2961/
$mp3['流派']=ord(fread($fp,1));
return $mp3;
}
}

生成mp3列表:

<?

//调用方法getDir(“./dir”)……可以是绝对路径也可以是相对路径
$filelist = getFile(“/home/test”);
//var_dump($filelist);
foreach($filelist as $file){
echo(“<li><input type=\”button\” onclick=\”checkMe(‘play.php?file=”.$file.”‘)\” value=\””.$file.”\”<br />”);
$mp3 = readmp3($file);
if($mp3){
echo($mp3[‘艺术家’].’-‘.$mp3[‘专辑’].’-‘.$mp3[‘标题’]);
}
}
?>
</ul>
<input type=”button” onclick=”checkMe(‘play.php?’)” value=”stop” />

页面基本完成了。

然后是play.php,根据传进来的文件名,通过后台播放:

<?php
$cmdline = “/usr/bin/sudo /usr/bin/killall mpg123 >/dev/null &”;
shell_exec($cmdline);
if($_GET[‘file’]){
$cmdline = “/usr/bin/sudo /usr/bin/mpg123 –loop -1 “.$_GET[‘file’].” >/dev/null &”;
echo($cmdline);
$output = shell_exec($cmdline);
echo($output);
}
?>

基本上大功告成了,这里的mp3文件名除了本地文件外,还可以是流媒体或者网址,都可以试试看。

英文中有个词是couch potato,我还是当bed potato吧。好好享受着音乐吧。

 

附:Raspberry Pi(树莓派)声音输出的设置

Raspberry Pi(树莓派)声音输出可以设置为自动,耳机输出,从HDMI输出三种,默认为自动

pi@aborn ~ $ sudo apt-get install alsa-utils
pi@aborn ~ $ sudo modprobe snd-bcm2835    #把声音模块加入内核
pi@aborn ~ $ sudo aplay /usr/share/sounds/alsa/Front_Center.wav
pi@aborn /opt/vc $ sudo amixer cset numid=3 2
numid=3,iface=MIXER,name=’PCM Playback Route’
; type=INTEGER,access=rw——,values=1,min=0,max=2,step=0
: values=2
pi@aborn /opt/vc $ sudo aplay /usr/share/sounds/alsa/Front_Center.wav
Playing WAVE ‘/usr/share/sounds/alsa/Front_Center.wav’ : Signed 16 bit Little Endian, Rate 48000 Hz, Mono
pi@aborn /opt/vc $ sudo amixer cset numid=3
numid=3,iface=MIXER,name=’PCM Playback Route’
; type=INTEGER,access=rw——,values=1,min=0,max=2,step=0
: values=0

pi@aborn /opt/vc $ sudo amixer cset numid=3 1
numid=3,iface=MIXER,name=’PCM Playback Route’
; type=INTEGER,access=rw——,values=1,min=0,max=2,step=0
: values=1

values取不同的值分别代表:
0=auto(自动), 1=headphones(耳机), 2=hdmi

php读取mp3文件信息 (转)

一个读取的程序。其实稍作改动,就可以变成读写的(id3v1),id3v2复杂的多,以后看情况再写吧。
<?php
$file=”回到我身边.mp3″; //要读取的文件–俺偶像的
$mp3info=readmp3($file); //获得文件信息,数组
print_r($mp3info); //输出数组
function readmp3($mp3_file)
{
$fp=fopen($mp3_file,”rb”); //读取mp3文件
//首先判断是否有TAG,如果没有,那就没必要读取了,方法就是读取倒数128-126字节,看是否是TAG
//详情参看http://www.readlog.cn/archives/2961/
fseek($fp,-128,SEEK_END); //指针移到倒数128字节处
$tag=fread($fp,3); //读取倒数128-126字节位置的数据
if($tag==”TAG”) //如果这3个字节是TAG,表明有TAG
{
$mp3=array();
//标题30个字节,从倒数125字节到倒数96字节
//现在直接读就可以了
$mp3[‘标题’]=fread($fp,30);
//艺术家30个字节,从倒数95字节到66字节
$mp3[‘艺术家’]=fread($fp,30);
//专辑30个字节,从倒数65字节到36字节
$mp3[‘专辑’]=fread($fp,30);
//年份4个字节,从倒数35字节到32字节
$mp3[‘年份’]=fread($fp,4);
//注释28个字节,从倒数31字节到4字节 (有的是30个字节,那就把倒数第2,3位归入注释了)
$mp3[‘注释’]=fread($fp,28);
fseek($fp,1,SEEK_CUR); //跳过倒数第3位保留位
//第几首1个字节,倒数第2位
$mp3[‘编号’]=ord(fread($fp,1));
//流派1个字节,就是倒数第一个字节了
//流派这里是存放的整型数据,可以写个函数来把数字变成具体的文字。
//具体含义参看http://www.readlog.cn/archives/2961/
$mp3[‘流派’]=ord(fread($fp,1));
return $mp3;
}
}
?>

mpg123的循环播放

MPG123,听音乐最好能使用一个表(文件)把要播放的歌曲目录存在表里面:view plaincopy to clipboardprint?
find . -name “*.mp3” | sed ‘s/\.\///’ | sort > list.lst
find . -name “*.mp3” | sed ‘s/\.\///’ | sort > list.lst  播放的时候就可以:view plaincopy to clipboardprint?
mpg123 –list list.lst
mpg123 –list list.lst如果要循环的话可以加入–loop选项:view plaincopy to clipboardprint?
mpg123 –loop -1  songname.mp3
//-1(<0)的数表示无限循环,也可以指定确定的次数。只能是单首循环。
//这个–loop 参数如果用来播放List(文件)中的歌曲时
//是不能够达到重头到尾的重复播放的效果的,只是循环第一首。

//如果要循环目录内容的话,目前可以:
mpg123 –list list.lst -Z
//用于随机循环播放
mpg123 –loop -1  songname.mp3
//-1(<0)的数表示无限循环,也可以指定确定的次数。只能是单首循环。
//这个–loop 参数如果用来播放List(文件)中的歌曲时
//是不能够达到重头到尾的重复播放的效果的,只是循环第一首。//如果要循环目录内容的话,目前可以:
mpg123 –list list.lst -Z
//用于随机循环播放

ffmpeg笔记

 

ffmpeg version N-43921-ga366bea 版本 视频转换参数详解

(转自http://www.cppblog.com/nenlong/archive/2012/09/18/191047.html)

libavutil 51. 70.100
libavcodec 54. 54.100
libavformat 54. 25.104
libavdevice 54. 2.100
libavfilter 3. 13.101
libswscale 2. 1.101
libswresample 0. 15.100
libpostproc 52. 0.100

rem -c:v libx264 视频解码器
rem libvpx copy libxvid mpeg4 mpeg2video rawvideo
rem -b:v 2000k 视频比特率 x264固定解码率是正确 其他的都不正确
rem -c:a libmp3lame 音频解码器
rem -b:a 128k 音频比特率

rem -q:v 1 固定视频量化标度(VBR) 0.1-31 1高 31最差 这时-b:v无效 以前是 -qscale n格式
rem mpeg4时 0.1=4335k 1=3835k 2=3403k 3=2186k 4=1678k 5=1336k 6=1158k 7=1003k 31=286k
rem -qmin 1 最小视频量化标度(VBR)
rem -qmax 1 最大视频量化标度(VBR)
rem -qcomp 1.0 视频量化标度压缩(VBR) 0.0-1.0

rem -sameq 同样视频质量 此时 -b:v -qscale 无效

rem -ss 00:20:00.000 转换开始时间 不能在 -i 后面
rem -t 00:01:10.000 转换总时间
rem -vframes 600 转换振幅总数
rem -s 720×404 转换分辨路
rem -aspect 16:9 设置横纵比
rem -g gop_size 设置图像组大小
rem -bf frames 使用frames B 帧,支持mpeg1,mpeg2,mpeg4
rem -qcomp compression 视频量化标度压缩(VBR)
rem -dc 设置dct的算法
rem -mbd 2 宏块决策算法(高质量模式) 0=mbcmp (default) 1=fewest bits 2=best rate distortion
rem 转换某时间段
rem ffmpeg -y -ss 00:20:00.000 -i in_xxx.wmv -t 00:00:03.000 -c:a libmp3lame -b:a 128k -c:v mpeg4 -sameq -g 12 -bf 2 -qcomp 0.2 -dc 10 -mbd 2 -aspect 16:9 -f avi -s 720×404 out_xxx.avi

rem 全部转换
rem ffmpeg -y -i in_xxx.wmv -c:a libmp3lame -b:a 128k -c:v mpeg4 -sameq -g 12 -bf 2 -qcomp 0.2 -dc 10 -mbd 2 -aspect 16:9 -f avi -s 720×404 out_xxx.avi

视频合并
mencoder 001 002 003 -oac copy -ovc copy -o jion.avi

获取摄像头
ffmpeg -y -f vfwcap -i 0 -c:v mpeg4 -q:v 1 -qmin 1 -s 640×480 -r 24 -g 12 -bf 2 -qcomp 0.2 -dc 10 -mbd 2 -aspect 4:3 -f avi cap.avi

上传照片并自动旋转

项目中有个需求,需要通过手机浏览器上传照片。本来是个很简单的事情,后来发现手机自带的陀螺仪会根据手机的方向变化而发生旋转,导致上传的照片容易发生偏转。后来查了一些资料,在图片的EXIF信息中包含了照片的方向。

下载了metadata-extractor类,用来解析照片中的exif信息。

通过下面的方法得到方向:

public static int getImageOrientationTag(File f){
Metadata metadata;
try {
metadata = JpegMetadataReader
.readMetadata(f);
Directory exifDirectory = metadata.getDirectory(ExifDirectory.class);

if(exifDirectory.containsTag(ExifDirectory.TAG_ORIENTATION)){
return exifDirectory.getInt(ExifDirectory.TAG_ORIENTATION);

}

} catch (JpegProcessingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (MetadataException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return -1;
}

下面的方法来旋转照片:

public static void autoRotateImageByExif(String srcFile,String desFile){

try {
File in = new File(srcFile); // 读入文件
BufferedImage src = javax.imageio.ImageIO.read(in);
int orientation = getImageOrientationTag(in);
switch (orientation) {
case 1:
case -1:   //不需要旋转
FileUtil.copyFile(srcFile, desFile);
break;
case 8: //旋转270度
rotateImg(src, 270, Color.BLACK, desFile);
break;
case 3: //旋转180度
rotateImg(src, 180, Color.BLACK, desFile);
break;
case 6: //旋转90度
rotateImg(src, 90, Color.BLACK, desFile);
break;
default:
break;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} // 构造Image对象

}

根据exif权威解释,总共有8种方向,另外四种除了旋转以外,还有镜像,根据手头的测试,没有发生镜像问题,所以就把它忽略掉了。

虾米网音乐下载

为了下载虾米的音乐,网上找了不少帖子,自己写程序来解密地址加密。解密以后发现操作还是太复杂,干脆用了这个懒办法。
1.先找到音乐id
比如打开音乐的链接如下:
http://www.xiami.com/song/play?ids=/song/playlist/id/3297547/object_name/default/object_id/0

id就是3297547

2.拼下面的地址
http://www.xiami.com/app/iphone/song/id/3297547

把后面的数字换成前面的id

3.打开改地址
内容大概如下:
{“song_id”:”3297547″,”default_resource_id”:”164782″,”length”:”237″,”category”:null,”listen_file”:”\/aliyunos\/62\/7062\/297623\/3297547_164782_l.mp3″,”album_id”:”297623″,”name”:”\u306a\u3054\u308a\u96ea “,”artist_name”:”\u590f\u5ddd\u308a\u307f”,”artist_id”:”7062″,”title_url”:”yi”,”recommends”:”50″,”singers”:”\u590f\u5ddd\u308a\u307f”,”title”:”\u6b4c\u3055\u304c\u3057~\u30ea\u30af\u30a8\u30b9\u30c8\u30ab\u30d0\u30fc\u30a2\u30eb\u30d0\u30e0~ “,”album_logo”:”http:\/\/img.xiami.com\/images\/album\/img62\/7062\/297623_2.jpg”,”location”:”http:\/\/m1.file.xiami.com\/62\/7062\/297623\/3297547_164782_l.mp3″,”low_size”:”9489600″,”file_size”:null,”low_hash”:”d633a228ae032c0b0223618f367b2fbb”,”whole_hash”:”d633a228ae032c0b0223618f367b2fbb”,”content_hash”:”d633a228ae032c0b0223618f367b2fbb”,”content_size”:”9489600″,”lock_lrc”:”2″,”lyric”:”http:\/\/img.xiami.com\/lyric\/upload\/47\/3297547_1252216310.lrc”,”year_play”:”6694″,”grade”:”-1″,”album_url”:”http:\/\/www.xiami.com\/app\/iphone\/albuminfo?id=297623&uid=”,”artist_url”:”http:\/\/www.xiami.com\/app\/iphone\/artistinfo?id=7062&uid=”,”isad”:”0″}

其中的location是没有加密的地址:
http:\/\/m1.file.xiami.com\/62\/7062\/297623\/3297547_164782_l.mp3

然后把”\”全部去掉就是完整的mp3地址了,想下载或者在线播放都可以了。

vmware无法在ubuntu上安装

在ubuntu server上安装vmware总出错,google以后,运行以下命令解决

sudo apt-get install build-essential

sudo apt-get install linux-headers-$(uname -r)

 

Ubuntu 13.04是最新的3.0的Linux内核,其内核版本的头文件的位置发生了变化,

导致之前,相对旧的VMWare Tools,找不到对应的头文件,因此而报错。

解决办法:

用当前,实际上已经存在的头文件,做个软链接:

 

sudo ln -s /usr/src/linux-headers-$(uname -r)/include/generated/uapi/linux/version.h /usr/src/linux-headers-$(uname -r)/include/linux/version.h

 

就可以重新运行vmware安装程序了。

通过google voice发送短信

手机上一直装了几个应用,用来给美国手机发送短信,每次都需要登录,比较麻烦。最近也想做一个小应用,其中通过手机发送验证码,觉得google voice最能满足这个要求,反正免费的不用白不用。

在网上找了一些源码,看看如何通过程序来发送短信,基本由三个版本,两个php版,其中一个zend加密版本,被pass掉,另外一个可能接口有些变更,好像发送不太成功。另外还找到一个java版本,测试了一下,可以成功发送,感谢原作者xinghuo.yao的无私奉献。从google code下载的代码,貌似作者是做了一个smsbot,但是我不需要这么复杂的功能,只把googlevoice实现部分摘出来了。

public class GoogleVoice implements Serializable {

/**
*
*/
private static final long serialVersionUID = 5889296580959689523L;
private String email;
private String password;

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

private String auth;
private String rnr;

private long lastSessionTime = 0;

public long getLastSessionTime() {
return lastSessionTime;
}

public void setLastSessionTime(long lastSessionTime) {
this.lastSessionTime = lastSessionTime;
}

public GoogleVoice(String email, String password)
throws AuthenticationException {
this.email = email;
this.password = password;
signIn();
}

private void signIn() throws AuthenticationException {
retrieveLoginAuth();
retrieveRnr();
lastSessionTime = System.currentTimeMillis();
}

public boolean sendSms(String mobile, String message) {
if (!checkSession())
return false;
try {
String payload = “id=&phoneNumber=” + mobile + “&text=”
+ URLEncoder.encode(message, “UTF-8”) + “&_rnr_se=”
+ URLEncoder.encode(rnr, “UTF-8”);
String data = fetchData(“https://www.google.com/voice/sms/send/”,
payload, auth);
// Should return {“ok”:true,”data”:{“code”:0}}
if (data.contains(“:true”))
return true;
else
return false;
} catch (Exception e) {
return false;
}
}

private boolean checkSession() {
if (System.currentTimeMillis() – lastSessionTime >= 1800000l)
return false;
lastSessionTime = System.currentTimeMillis();
return true;
}

private void retrieveLoginAuth() throws AuthenticationException {
String payload = “accountType=GOOGLE&Email=” + email + “&Passwd=”
+ password + “&service=grandcentral&source=” + “GAE”
+ “-GoogleVoiceTool”;
try {
String data = fetchData(
“https://www.google.com/accounts/ClientLogin”, payload,
null);
int index = data.indexOf(“Auth=”);
if (index != -1 && index + 5 < data.length())
auth = data.substring(data.indexOf(“Auth=”) + 5).trim();
if (StringUtil.isEmptyOrWhitespace(auth))
throw new AuthenticationException(“Get Login Auth failed”);
} catch (Exception e) {
throw new AuthenticationException(e.getMessage());
}
}

private void retrieveRnr() throws AuthenticationException {
try {
String data = fetchData(“https://www.google.com/voice/m/”, null,
auth);
Pattern p = Pattern.compile(
“<input.*?name=\”_rnr_se\”.*?value=\”(.*?)\””,
Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(data);

if (m.find())
rnr = m.group(1);
if (StringUtil.isEmptyOrWhitespace(rnr))
throw new AuthenticationException(“Get rnrSEE failed”);
} catch (Exception e) {
throw new AuthenticationException(e.getMessage());
}
}

private String fetchData(String url, String payload, String auth)
throws Exception {
HttpURLConnection con = (HttpURLConnection) new URL(url)
.openConnection();
if (auth != null)
con.setRequestProperty(“Authorization”, “GoogleLogin auth=” + auth);
con
.setRequestProperty(
“User-Agent”,
“Mozilla/5.0 (iPhone; U; CPU iPhone OS 2_2_1 like Mac OS X; en-us) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5H11 Safari/525.20”);
con.setRequestProperty(“Content-Type”,
“application/x-www-form-urlencoded”);
if (payload == null)
con.setRequestMethod(“GET”);
else {
con.setDoOutput(true);
con.setRequestMethod(“POST”);
OutputStream os = con.getOutputStream(); // 输出流,写数据
os.write(payload.getBytes(“UTF-8”));
os.flush();
os.close();
}
int code = con.getResponseCode();
if (code == 200) {
String response = getContent(con.getInputStream(), code);
con.disconnect();
return response;
} else {
String response = getContent(con.getErrorStream(), code);
con.disconnect();
throw new AuthenticationException(response);
}
}

private String getContent(InputStream in, int code) throws Exception {
BufferedReader reader = new BufferedReader(new InputStreamReader(in,
“UTF-8”)); // 读取结果
StringBuffer sb = new StringBuffer(“”);
String line;
while ((line = reader.readLine()) != null) {
sb.append(line).append(“\r\n”);
if (code != 200 && line.startsWith(“Error=”)) {
reader.close();
return line.substring(6);
}
}
reader.close();
if (code != 200)
return String.valueOf(code);
return sb.toString();
}

public static void main(String[] args) throws AuthenticationException{
GoogleVoice gv = new GoogleVoice(“用户名”, “密码”);
if (gv.sendSms(“手机号码”, “hello”))
System.out.println(“短信已发送至:”);
else
System.out.println(“短信未发送”);
}
}

 

 

早在一两年前,gv貌似还能全世界发短信,后来只限定在美加,不过对于我来说这个已经足够了。再次感谢作者无私奉献,感谢google无私奉献,但愿google别把这个接口给封了。

wordpress首页只显示指定栏目

这个blog建了挺久了,一直是乱七八糟的帖子混在一起,首页比较混乱,所以想把首页只放一些原创的非技术的帖子。

在网上找了很多方法,有的需要修改源代码,有的装插件。修改源代码的方法不适合将来升级(虽然说上次升级导致博客无法打开),所以还是用插件比较好。

网上推荐用Front Page Excluded Categories装了这个插件似乎不生效。所以又装了Ultimate Category Excluder,装上并启用以后在setting里面Category Exclusion里面选上你要过滤掉的目录就可以了。这个插件的神奇之处在于,你可以选择只滤掉首页,feed,search等不过滤,这样既可以隐藏首页不想要的东西,又不影响搜索引擎及订阅的内容。赞一个。

在树莓派上使用RS232(连接到Psion5)

原文地址:http://blog.mrpjevans.com/2012/1 … ry-pi-to-a-psion-5/

(笔者注:Psion5是Psion公司出的一款掌上电脑)

树莓派的通用输入输出口(GPIO)由26针组成,是黑客们的最爱,能够使用模拟或者数字信号的操作。翻遍了手册,我发现居然连基本的串口都没有。也就是我们上个世纪的老朋友,RS232,这是一个低功耗版本。对于那些完全不知道我说什么的人,不用担心,即使这个帖子不太适合你。RS232看起来像是以前那些学校废弃的技术,但实际上它是我们身边最简单的两机通讯的方式。

庆幸的是,搞Pi的那些聪明的家伙,使用串口作为控制台,也就是说,你可以用它登录然后得到一个命令行。我白天的工作就是在一个数据中心管理一堆的服务器。尽管他们有很多最新的、功能强大的工具包,无一例外的是他们都配有串口。当显卡不能正常工作时,至少你还可以通过这个接口来登录系统。

Pi上提供的串口使用起来很简单。只需要4条线:电源,发送,接收,地。没有更简单的方法了,直接把这些线连接到电脑的COM口,对不对?

嗯,不对。这其中有一个问题,Pi用的电压是3.3v,RS232需要+12V作为高电平(1),-12v作为低电平(0)。Pi自身没办法做到,通过google可以找到很多现成的解决方案。幸运的是,有一个现成的芯片可以双向转换信号,让我们可以从pi的低电压信号转换成一个“真正的”RS232接口。这个价格大概是5镑,名字叫MAX3232CPE。只需要小部分的电容就可以。

到了我们开始干活的时候了。我从本地的Maplin买到了所有的配件(下面提供了链接和编号):
一个Max2323CPE集成电路(DT26D)
一个16针DIL IC插座(BL19V)(如果你有面包板,这个就不需要了)
5个0.1uF电容(N43CJ)
9针D-Type插座
线
杜邦线(A39GF)
一些洞洞板(FL17T)(虽然我强烈建议一开始用面包板)

当然还有:
一点焊接经验
一个COM/串口

我这里还出现了一个问题。作为Mac用户,我知道乔布斯多年前就放弃了RS232口,采用兼容性很好的usb接口。幸好Maplin还卖一个基于PL2303芯片usb转串口的适配器,在OS X上运行的很好,包括山狮,但是我花了不少时间来找驱动和步骤。

开始干活,这就是我们要做的:


最开始我在面包板上完成了,按照Joonas Pihlajamaa的步骤(链接在文末)。如果你还是个新手,在面包板上插IC芯片,还是要小心一些,把所有的针脚都插进去。在这个时候不需要用插座。下一步,我焊接了一个9针的连接器。我把RXD焊到针脚2,TXD焊到针脚3,地为针脚5(右上)。

现在你关闭Pi,从集成电路的1,6,8,10针脚连接这4条线到Pi。针脚1时左上,标记为P1。在它右边是针脚2。然后针脚1下是3,右边是4,以此类推。

这四条线是这么连接的:
Pin 1 – +3.3V
Pin 6 – Ground
Pin 8 – TXD (发送数据)
Pin 10 – RXD (接收数据)

将9芯的RS232连接到你的COM接口,然后打开Pi。
你的Pi应该正常启动,根本不知道建了新连接。现在把你的注意力放到你的电脑。

你需要有个软件能够连接到你的Pi。在windows上,你可以用PuTTY。在mac上,试试看MacWise,或者直接用linux上的命令行工具,比如screen

如果你打算用screen,来看看他是和么安装的

  1. $ screen -h

复制代码

命令不存在?那就安装吧

  1. $ apt-get install screen</p><p>$ screen /dev/ttyUSB0 115200

复制代码

或者你已经安装了MacPorts

  1. $ port install screen</p><p>$ screen /dev/tty.usbserial 115200

复制代码

注意:在/dev/可能有很多设备,取决于操作系统和驱动程序等。看看你的/dev/目录下是不是存在。可以找tty或者usb开头的那些。

屏幕应该会变成空白,按一次回车键后会出现登陆提示,然后可以到Pi的配置。

如果你用一个更高级的包,记住RS232工作前还需要配置。Pi的设置是115200bps(波特率),8位,无校验,一个停止符。这个通常标记为115200 8N1,你需要改成这个设置。一旦配置好,打开或者连接(取决于你软件怎么用)然后按回车就可以了。Pi的登录提示应该就会出来了。

无法运行?十之八九是你PC端的的RXD和TXD没接对。断开连接关闭Pi,在面包板上把这两条线换一下。如果这样还不工作,检查你终端的设置。

我决定通过给Pi届一个屏幕和键盘让它得到一个合乎逻辑的结论(在我的脑子里),也就是Psion5。然后一开始无法正常工作,因为不管是Psion还是Pi都希望自己是可以和电脑通信的“客户端”。我需要一个交叉线,把RXD和TXD交换一下,最后可以跑了。


只要在面包板上可以运行了,就很容易把IC移植到洞洞板,让它做一些持久地工作。

你可能奇怪为什么要这么做,事实是很多设备依旧在使用RS232通信。你可以在投影机、机顶盒甚至车上找到RS232接口。即使我一个很老的洗衣机上也有一个。所以,让Pi拥有一个很好用的RS232接口将会很有意思。通过google你还可以将目前登录命令行改成你想要的。我将会怎么用它?它将会是另外一个贴子。

Sources for this article:
Joonas Pihlajamaa
http://codeandlife.com/2012/07/01/raspberry-pi-serial-console-with-max3232cpe/

speakjava
https://blogs.oracle.com/speakjava/entry/serial_communications_with_a_raspberry

通过手机来控制家电

心血来潮想通过树莓派对家里的电器进行控制,网上查了不少资料,决定动手一试。首先决定对电暖器开刀,这个电脑有一个红外的遥控器,可以开关、定时、设定高低档功能,我要做的就是模拟遥控器对其发出指令。初级篇,通过电脑命令行进行控制,高级篇使用手机进行控制。

参照baoxiaozhong的红外接收http://www.shumeipai.net/thread-12265-1-1.html 设置好了红外接收器,然后尝试用相似的方法实现了红外发射器,成功控制电暖器,后续将考虑控制电视,空调等 设备。

初级篇:用电脑来控制电暖器

原理:

先通过红外接收模块,采集遥控器的指令,然后通过红外发射器模块模拟遥控器发送红外指令控制。

环境:xbian 1.0 alpha4

硬件:taobao上淘的10多块一个的红外接收模块及红外接收模块,此处不发地址,免得广告嫌疑。

连接方式:

红外接收器
vcc 连 pin1 (3.3v)
gnd 连 pin6(ground)
data连 pin12(gpio18)
红外发射器
vcc 连pin2(5v)
gnd连pin6(ground)
data连pin11(gpio17)

为什么这么连,我查了很久资料,后来在lirc_rpi原作者网站看到了,大概固定在程序里面了。
地址:http://aron.ws/projects/lirc_rpi/

步骤:
先通过红外接收器接收遥控器的编码,请参照http://www.shumeipai.net/thread-12265-1-1.html.
在用户目录生成了lircd.conf文件

我生成了KEY_UP,KEY_DOWN,KEY_0,KEY_1等分别代替开启、定时、低、高四个按钮

然后将它拷贝到/etc/lirc/remotes下,
sudo cp /home/xbian/lircd.conf /etc/lirc/remotes/xxx.conf (xxx随便你起名字,但是要和后面统一)
sudo vi xxx.conf
修改 name /home/xbian/lircd.conf 为 name xxx

sudo /etc/lirc/lircd.conf
增加一行

include “/etc/lirc/remotes/xxx.conf”

保存退出
现在可以测试了
sudo irsend SEND_ONCE xxx KEY_ON
sudo irsend SEND_ONCE xxx KEY_TIMER
sudo irsend SEND_ONCE xxx KEY_LOW
sudo irsend SEND_ONCE xxx KEY_HIGH

开始享受电暖器滴滴接收命令的的声音吧。

高级篇:通过手机来控制电暖器

安装LNMP
参照http://geekpi.cn/blog/2012/10/1908

apt-get install mysql-server mysql-client nginx php5 php5-fpm php5-mysql php5-curl php5-gd php5-intl php-pear php5-imagick php5-imap php5-mcrypt php5-memcache php5-ming php5-ps
php5-pspell php5-recode php5-snmp php5-sqlite php5-tidy php5-xmlrpc php5-xsl

mysql我没有做优化

配置nginx
先配置/etc/nginx/nginx.conf,需要做的就是限定线程数和开启gzip支持,gzip开启后将大幅降低传输html的流量占用。

worker_processes 1; #只有一个CPU,单进程即可

worker_connections 256; #一般支持100在线连接就达到raspberry pi的极限了

gzip on; #gzip开启取消前面的#让默认设置生效即可
gzip_disable “msie6”;

gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

接下来设置/etc/nginx/sites-avaliable/default ,配置站点属性

root /var/www ; #站点存储位置

index index.php index.html index.htm; #加入index.php为默认页面

location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;

fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}

#开启php解析,使用php-fpm作为Fastcgi通信模块

然后配置php sudo权限,这样php执行命令的时候不需要输入自己的密码
为 nginx,而想透过 PHP 发送irsend,用 root 输入指令 vi /etc/sudoers,
在档案最底加上以下一行:

www-data ALL=NOPASSWD: /usr/local/bin/irsend

在/usr/share/nginx/www/下 编写cmd.php

<?php
$cmd = $_POST[‘cmd’];
if(!$cmd){
$cmd = $_GET[‘cmd’];
}
$device = $_POST[‘device’];
if(!$device){
$device = $_GET[‘device’];
}
if($cmd&$device){
$cmdline = “/usr/bin/sudo /usr/local/bin/irsend SEND_ONCE “.$device.” “.$cmd ;
echo($cmdline);
$output = shell_exec($cmdline);
echo($output);
}
?>

然后就可以通过http://ip地址/cmd.php?cmd=KEY_UP&device=xxx控制你的设备了。
这里的xxx是可以不同设备的哦。看你前面irrecord里面配置的

当然这种方式操作不方便,和shell操作差不多,所以可以自己做一个html页面,放上若干按钮,每个按钮分别调用cmd.php上面的指令。

这是个简单的例子

<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />
<meta name=”apple-mobile-web-app-capable” content=”yes”>
<title>智能家庭控制台</title>
<script type=”text/javascript” src=”js/jquary-1.7.1.js”></script>
<script type=”text/javascript”>
var xmlHttp;
//创建XMLHttpRequest对象
function createXMLHttpRequest(){
if (window.ActiveXObject){
xmlHttp=new ActiveXObject(“Microsoft.XMLHTTP”);
}else if (window.XMLHttpRequest){
xmlHttp=new XMLHttpRequest();
}
}
function checkMe(url){
createXMLHttpRequest();
xmlHttp.open(“post”,url,true);
xmlHttp.onreadystatechange=send; //用send函数进行发数
xmlHttp.setRequestHeader(“Content-Type”,”application/x-www-form-urlencoded;”);
xmlHttp.send(null);
}
function send(){
//alert(“指令成功发送!”);
}
</script>
</head>

<body>

<div id=”content”>
<div id=”menu_mode”>
<ul>
<li><input type=”button” onclick=”checkMe(‘cmd.php?cmd=KEY_ON&device=heater’)” value=”开/关”/></li>
<li><input type=”button” onclick=”checkMe(‘cmd.php?cmd=KEY_LOW&device=heater’)” value=”低档”/></li>
<li><input type=”button” onclick=”checkMe(‘cmd.php?cmd=KEY_HIGH&device=heater’)” value=”高档”/></li>
<li><input type=”button” onclick=”checkMe(‘cmd.php?cmd=KEY_HIGH&device=heater’)” value=”定时”/></li>
</ul>
</div>
</div>
</body>
</html>

然后通过http://ip地址/index.html访问

对于使用iphone或者ipad的用户,还可以把网页快捷方式放到主屏幕,打开就是一个操作界面,是不是很来福啊?

通过树莓派从近太空发回实时图像 [翻译]

原文地址:

http://www.daveakerman.com/?p=592

越来越多的人喜欢访HAB(放高空气球),爱好者使用标准气象气球将小设备(一般100克到1公斤)发送到近太空(大概距地面30公里),一般会携带跟踪设备(这样可以在飞行过程中知道气球的位置),并且通常会带一些传感器(比如温度、压力等),有的还携带摄像机或照相机,将照片保存在SD卡中,方便之后取回。 跟踪器的作用是从GPS接收器读取作为,可能的话,读取传感器的内容,按照一定的格式通过低功率无线设备发回地面。飞行必须通过预定的路线,保证安全的情况下飞行,比如说避开机场和人口密集地区,并申请许可,比如在英国需要的到CAA的许可。我们使用70厘米无线频率(大概是434MHz),使用RTTY(无线电报)发送遥感信息到一些地面由其他爱好者建的接收站。从接收器接收到的遥感信号都会发送到中央服务器,并画出实时的地图,只要连上英特网大家都能看到。这个系统运行的非常好,已经被用来跟踪800公里距离的小设备,但是发射器必须低于英国法律规定的10mW。

五月初我接收到我第一个树莓派计算机,在我准备利用飞行计算机之前,已经放飞了好几次高空气球。前几次基本都是用Arduino迷你板,因为它很小,轻到几乎没有,简单,并且很省电。对比Pi,感觉它没有任何优势。当我看到它的usb口可以提供快速、简单、廉价网络摄像头,也就是说我可以提供实时地照片(SSDV),这个大概尝试的人不多。

近太空是个比较恶劣的环境 – 不到1%的空气,温度低至零下50度,任何一个东西出问题,他就会一直出问题。无线链接是单向的,也就是说没有机会远程做类似”sudo reboot”的操作,让它关机并重新启动!下降过程非常暴力,所以即使是SD卡插座也是一个潜在的失败因素。PI比我们通常的主板复杂,没有SD卡,没有USB,甚至没有操作系统,所以额外的电力和功能都是由代价的,第一个是增加大约60-500毫安的电流,意味着更高的功耗。人们一直都担心近太空的低温,如果你的设备只靠几瓦的电力驱动,这也许就不再是个问题。我反而更担心设备中间变得太热,所以我在PI上加了散热片。

我用特殊的热粘合胶把散热片粘在USB/以太网芯片上以及3.3v稳压器上。他们通常都会变暖但是不会太热,我担心在1%稀薄空气中(对流太少)他们会变得太热。你还可以看到有两条线直接连接5V,比使用一个连接器,焊接更可靠一些。另外一个修改是拆除了S2的视频接口,可以增加空间容纳我的扩展板。最后的修改是降低USB保险,因为我的摄像头电流需求超过其额定值。然后我增加了一块板来安装Radiometrix NTX2无线发射器来发送遥测及图像到地面,并连接到一个简单的GPS接收器上的线尾,这样他可以远离我的发射器。

最后的一项是合适的电源。劲量锂AA电池是显而易见的选择,因为它们可以在零下40摄氏度条件下工作到,而且适合大电流(500mA以上的PI加上网络摄像头)。在30公里上空,通常会降到零下50度,即使只有最少绝缘,电池自身发热也能保证其在可控范围。PI需要5V电压,所以我用6个AA电池加一个外部的低压降线形稳压器给它提供足够的电压,直到没电为止。稳压器大概有3瓦,所以需要一个散热片。对于小负载来说,这个热量太高,因为这是绝缘体。当然你也不想它变得太冷,因为这样也会影响其它部件。我订购了一些开关稳压器,但是在我放飞之前还没到货,我只好用线性稳压器。

通常,NTX2通过GPIO口发送1或者0,以一定的速率发送无线电报(RTTY),比如每隔20ms,按照50波特率。如果是在AVR或者PIC单片机上,这个非常容易,只需要设置延时或者时间中断。但是Pi运行的不

是实时操作系统,我无法控制一个正确的时序,特别是当系统正在忙于拍照。还有其它的方式,但我选择了最简单的方式,通过串口来控制NTX2。RTTY使用正常的RS232串行标志和占空以及停止位,所以

为什么不用硬件的UART来做计时呢?没有花太多时间写了一小段C程序来以4800bps打开串口,读取GPS数据来获取经纬度及海拔,然后关闭端口,并重新以300bps发送电报(我发现如果不先关闭再重新打

开串口,经常不太稳定)。当然,做这个的时候,需要关闭串口的登陆提示以及内核消息,但总之还是比较简单。我将一个标准的Debian镜像写在一个4G的SD卡上。

为了获取实时的图像,我只能给debian打了一个补丁,终于能够将摄像头识别为/dev/video0.我尝试了好几种摄像头,最后选择了罗技德C270,他能够提供比较合理的质量、亮度,并且不贵(如果所有

设备都找不回来的话)。我尝试了好几种图片获取程序,最后觉得fswebcam最好。别忘了,无线系统带宽很低,通常要飞2个小时,所以我们没有时间发送大图片,所以没有必要选择非常好的摄像头和高

解析度。我权衡了质量和传输速度,觉得432×240的分辨率,50%压缩率比较适合。 我测量了摄像头电流,空闲时50mA,拍照时大概是250mA,所以需要缩减USB保险(最大140mA).写了一个脚本每30秒拍

张照,保存在SD卡上,跟踪程序会选择最好的照片(最大的文件)进行传输。每个选中的文件会转化成适合下载的格式(分成块,每块都带FEC校验),每次发送一块。我把图片数据分散在无线电报中-每

个电报中包含四个图像数据包。这是PI的自拍照:

经过完整的试验和测试,取得CAA的许可,我作了一个盒子,里面装了Pi、摄像头、GPS、电池和稳压器。我不想使用太多绝缘体,这样才不会使里面太热,所以我用了10mm的EPX材料。低于这个厚度的话

,可能会变形。

升空那天,根据风向,预计会按照S型轨迹飞行,从我家(West Berkshire)附近的升空地点,先向南,再向东,然后一直向北,直到在高海拔的地方转向西面。下降的时候,会按照相反的顺序改变方向

,最后降落在Chilterns附近。当天天气不错,应该不会出现意外,我开始给气球充气。我申请了可以飞两次,所以我的朋友兼爱好者Anthony Stirk可以放飞他做的跟踪器。因为有3个跟踪器以及两次飞

行许可,我们选择了升空一个带小光线跟踪的大气球,另外一个气球带上了Anthony的大跟踪器和一个GoPro高清摄像机,然后把Pi放里面。经过一番思考,我们决定把第三个跟踪器作为备份,确保GoPro

能够找回来。

放飞的那天终于来了,同时也等来了雨,因为天气预报是阵雨,我们就到升空地等到变成了毛毛雨。我们先放飞了带着小负载的大气球,这样Anthony可以尝试记录坐标。然后我们放飞了后面这个复杂的

东东,我的Pi在最上面,然后是GoPro,最后下面是备用的Buzz跟踪器。这张是飞行前的Pi:

和即将升空的气球:

整个一串东西,包括降落伞和3个设备大概1kg左右(何我最初试验相同),从气球到最低的设备大概有60米长。升空非常有趣,最开始风很小,几乎是垂直升空。后来风稳定了,气球按照一个角度升空

,它可以顺利的按照我能达到的最快速度升上去。直到顺利升空我才放松下来。这巨大一串东西冲入云中,让人印象非常深刻。

升空地在我住的村庄,之后我们开车回到家中,在“任务监控中心”看它传回来的照片。预计的落地点不远,我没不需要急急忙忙的去追赶,我们有足够的时间回来看照片并吃点东西。

第一架飞行器是海拔高度尝试,根据经使用的制造商和大小,要不在27公里之前就爆炸了,要不超过预计范围,跑到了40公里之外。实际上,前几个地方的海拔高度纪录表都是用这个牌子和尺寸。Anthony一直就在看紧紧盯住屏幕看遥感数据。

那个时候,我当然更关心树莓派到底运行得怎么样。GPS位置还显示在发射场地,这是个明确的干扰GPS信号。我还没确定是不是,但GPS接收器和天线非常靠近Pi和摄像头。下次我会增加一些距离。然而图像很好的传输过来了,不仅通过我家的天线和接收器,也可以通过全国各地的其他接收机接收。气球升的越高,图像的质量更好,越来越多的接收器接收到了更好的图像,甚至远在北爱尔兰(远在500公里之外,对于10mW已经很不错了)。现在饼型飞行还没完全出来。下图是一个饼图显示了不同的监听器接收到的图片数量。

第一架飞行器还在不断的攀升,最终达到了第4区,只比世界纪录低了300多米。一方面我希望它飞得更高些,一方面我很高兴它没有在第二区就挂掉。然后,气球爆炸了,最初下降还算正常。但是多数气球还挂在上面,成功地变成了一个降落伞的形状,速度减到大概2米每秒的速度,在这个高度,正常速度应该是这个的5倍以上。谈到主要的飞行,它一张一张发回的图像,没有出现任何错误,而且一张比一张更好,直到飞到最后越来越高。

 


我们预期它在34公里处爆炸,但很明显气球不完全符合我们的计算。它经历了34公里,35公里,最终在40公里处爆炸(准确的说是39994米,在海拔记录里面排12位)。对于一个中等大小带着1公斤负重的气球来说,已经非常惊人了。气球爆炸了,也就是该我们取出追车了,两辆车都配备了天线、无线电接收器、解码和底土,还有3G网络。预计降落点靠近Didcot,所以我们前往那里,然后停车确认最新的预测降落点。设备最终降落在密尔顿高地,我们离它不远,离发射场只有几英里。令我们惊讶的是,有一个接收器离它非常近,接收到了实时的图像。过了一段时间,大家都能看到设备落到了长长的草丛里面。


Anthony最先从他的车里看到设备,在球场边上的草丛里。得到俱乐部的允许,我们拿回了所有3个设备和降落伞。

同时,前一个飞行物还在下降,但非常慢。只有我们预期的1/5.我们不知道具体的时间,但是我们知道已经被降落伞接管。然后在最后的几公里,它急剧下降(可能是乳胶撕毁了),最后降落在牛津北边的一块地上。这里的海拔不太常见:

花了我们不断地时间来找到它的位置,但它似乎在一个比较难靠近的地方。随着雨越来越大,Anthony 决定收工,而不是找一个只值50镑的跟踪器。然后他开走了。我上网告诉其他在UKHAS聊天室的爱好者我也要回家了,“它就在A34附近的停车场”,有人告诉我,“很容易就拿到”,“雨5分钟就停了”。嗯,好象没有那么糟,我往北开到A34,然后回到南边的停车处。

嗯,上面的三句话,只有第1条是正确的,只离停车处155米。但是暴雨一直在下,我只能在车里等。最后,我决定出去了,爬过树木和灌木丛去找,前面有片五尺高的玉米地。已知没找到那个设备。失败后,我走到车边,用我的anroid手机打开HamGPS软件来确定设备的位置。花了很多时间才到哪里,我感觉我在演“疯狂的戴夫”,当我到达目的地,我钻进了设备和气球中间的尼龙线。这的确看不到,直到我爬到最顶上,最终成功拿到。

所以,一切的一切,伟大的一天。所有的4个跟踪器全部回收,并且我们得到了令人惊叹的图像。如果有兴趣,可以访问UKHAS网站。更多的图像和视频,请访问:

All SSDV images

Photos from the day

pAVA Inflation Time-Lapse

Burst video from the GoPro

Launch video of PIE1, uAVA and BUZZ8

Landing video from the GoPro

Recovery of PIE1, uAVA and BUZZ8

Anthony’s Write-Up

感谢Anthony Stirk开车从阳光明媚的约克郡到最严峻最黑暗的Berkshire,并且提供GoPro HD相机, 感谢Phip Heron提供我们摄像头成像和编码软件,感谢Nick提供帮助,当然还要感谢我的妻子Julie让我们吃饱喝足,而且帮我开车,而我只需要做技术方面的东西。

 

 

通过Raspberry Pi实现无障碍上网

最近貌似google的服务实在不给力,搜索一直都无法打开。正好发挥手头树莓派的功能,来实现家庭无障碍上网。

网络环境:树莓派通过无线连接路由器,其他电脑通过树莓派中转,国内网址直接走路由器,被墙网址通过VPN出去。

首先设置树莓派,通过无线上网:

1.无线配置,修改/etc/network/interfaces,下面的SSID,PASSWORD换成你自己的

auto lo
iface lo inet loopback
iface eth0 inet dhcp
allow-hotplug wlan0
iface wlan0 inet static
address 192.168.88.10
netmask 255.255.255.0
gateway 192.168.88.1
wpa-ssid "SSID"
wpa-psk "PASSWORD"
wireless-power off

2.安装ppp客户端

sudo apt-get install pptp-linux

3.Next, Create a file in /etc/ppp/peers with arbitrary name and the following contents:
在/etc/ppp/peers目录创建一个文件,其中VPNHOSTNAME,$USERNAME,$PASSWORD换成你自己的帐号密码

pty "pptp $VPNHOSTNAME --nolaunchpppd --debug"
name $USERNAME
password $PASSWORD
remotename PPTP
require-mppe-128
require-mschap-v2
refuse-eap
refuse-pap
refuse-chap
refuse-mschap
noauth
debug
persist
maxfail 0
defaultroute
replacedefaultroute
usepeerdns

3.测试vpn拨号是否成功

sudo pon 配置文件名

然后ping www.facebook.com看是否通过。

4. 启动内核的IPv4转发

sudo sysctl -w net.ipv4.ip_forward=1
记得同时修改/etc/sysctl.conf保证重启也有效。

5.下载chnroutrs.py,用 chnroutes 生成路由脚本(google chnroutes.py,头条就是)

python chnroutes.py -p linux

会生成ip-down,ip-pre-on等文件。

执行ip-pre-on,会把所有的国内的ip地址段加入路由表。

6.在RPi中启动iptables的NAT转换

sudo iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE

 

后来验证似乎还需要这几条指令:

iptables -A INPUT -i ppp0 -j ACCEPT
iptables -A OUTPUT -o ppp0 -j ACCEPT
iptables -A POSTROUTING -t nat -o ppp0 -j MASQUERADE
iptables -A POSTROUTING -t nat -o wlan0 -j MASQUERADE

其中wlan0是你的无线网卡的id,如果只有一块网卡,就直接用这个,不需要改了。

 

在你的客户端电脑上把网关改成PI的ip地址,dns改成8.8.8.8或者8.8.4.4,防止国内dns污染。看看是不是可以打开facebook之类的网站了?

不确定的话,你可以ipconfig /flushdns后,tracert不同域名,看看是不是走不同路由出去的。

tracert www.china.com 这个应该是走路由器出去的

tracert www.facebook.com这个应该是走VPN的。

所有网站畅通无阻的出去了,包括google随便什么关键字都不会重置了。

 

后记:俺VPN流量有限制,所以都没有加到自动启动里面,每次登录上去手动启动一下就可以了。如果需要自动启动,可以参考其他文章。如果不想每次都要修改dns和网关,在pi上建一个dhcp服务器,网关,dns都配在里面,自动获得就可以了。

比如下面的方法,让系统自动启动VPN

To start your VPN client on boot, you can follow the instructions onhttp://pptpclient.sourceforge.net/howto-debian.phtml (point 8 or 9, Hand configuration section)

An alternate method to make your VPN client run on boot is to make a script in /etc/init.dcontaining these contents:

#! /bin/sh

case "$1" in
  start)
    pon $/etc/ppp/peers/FILENAME
    echo "PPTP Started"
    ;;
  stop)
    poff $/etc/ppp/peers/FILENAME
    echo "PPTP Stopped."
    ;;
  *)
    echo "Usage: /etc/init.d/blah {start|stop}"
    exit 1
    ;;
esac

exit 0

Then run:

update-rc.d [filename of script] defaults

To make it run at startup.

Raspberry Pi跑起来了

Raspberry Pi是什么?
引用维基百科的一句话:

The Raspberry Pi is a credit card sized single-board computer developed in the UK by the Raspberry Pi Foundation with the intention of stimulating the teaching of basic computer science in schools.

Pi 已经流行了一段时间了,找到一个开始测试。

入手第一件事,就是刷SD卡。从各个官网下载固件,然后烧到SD卡上。花了两天,把所有的固件都刷了一遍,总算把基本功能跑起来。

Raspberry PI官网固件,直接进桌面,体现了它的原始想法–教育,但是没有媒体功能,所有的东西都需要自己折腾,UI方面的折腾实在不想花太多时间,放弃。

Raspbmc,功能比较齐全,直接进入XBMC,Airplay只有声音没有图像,无线网卡无法启动,总不能从客厅拖一根网线到房间吧,只能放弃。

Openelec,直接进入XBMC,但是功能是在太精简,完全没办法在上面开发定制自己的功能,放弃。

Xbian,很精简,直接进入XBMC,无线网卡功能能用,但是Airplay直接无线。配置好了XBMC,加入中国视频网站的支持,至少摆在房间可以用来做播放器,后台可以用来做智能控制,就选这个了。

今天试了红外接收板接收遥控器信号,信号能够接收到,但是还没办法解码。或者不解码了,直接通过发射板发射出去好了,改天再研究。

实现目标,通过Pi能够通过红外来控制各种家电,比如电视、机顶盒、空调、dvd、取暖器;控制摄像头,可以实现监控;通过温度感应器,读取温度,然后启动取暖器或者空调;无障碍翻墙;做个定时撞钟发微博的机器人…