小子 发布的文章

树莓派 声控开关

接线

VCC -> 2(物理)
GND -> 6(物理)
OUT -> 7(物理)

2013-08-10 16.07.53.jpg

代码

#!/usr/bin/env python
# encoding: utf-8
# @author xiaozi <245565986@qq.com>

import RPi.GPIO as GPIO
import time

# pin: 物理7 -> 4

GPIO.setmode(GPIO.BCM)
GPIO.setup(4, GPIO.IN)

while 1:
    # 0是有声音,1是没声音
    print(GPIO.input(4))
    time.sleep(0.001)

树莓派 CPU内存监视

前提

需要一个 http服务器提供访问,还需要一个 websocket吐服务器数据,至于怎么编译nginx这边就不讲了

预览

屏幕快照 2013-08-06 下午2.29.19.png

代码

这里主要给出后端python的代码,前端主要是用backbone + smoothiecharts实现

#!/usr/bin/env python
# encoding: utf-8

import tornado.web
import tornado.websocket
import tornado.ioloop
import subprocess, threading, json, re

def vmstat():
	memoryKey = ['swpd', 'free', 'buff', 'cache', 'total']
	cpuKey = ['us', 'sy', 'id', 'wa']
	space = re.compile('\s+')
	memTotal = subprocess.check_output("cat /proc/meminfo | grep MemTotal | sed 's/\\w*:\\s*\\([0-9]*\\).*/\\1/'", shell = True).strip()
	# print(memTotal)
	# 这个地方要使用 shell = True 的话,需要记得退出的时候关闭子进程
	p = subprocess.Popen(['vmstat', '1', '-n'], stdout = subprocess.PIPE)
	io_loop = tornado.ioloop.IOLoop.instance()
	p.stdout.readline()
	p.stdout.readline()
	for line in iter(p.stdout.readline, ''):
		# print(line)
		fields = space.split(line.strip())
		memoryVal = fields[2: 6]
		memoryVal.append(memTotal)
		result = dict(memory=dict(zip(memoryKey, memoryVal)), cpu=dict(zip(cpuKey, fields[12: 16])))
		result = json.dumps(result)
		print(result)
		for waiter in MonitorHandler.waiters:
			io_loop.add_callback(waiter.write_message, result)

class MonitorHandler(tornado.websocket.WebSocketHandler):
	waiters = set()
	def open(self):
		MonitorHandler.waiters.add(self)
		print('waiters: ', len(MonitorHandler.waiters))
	def on_message(self, message):
		pass

	def on_close(self):
		MonitorHandler.waiters.remove(self)
		print('waiters: ', len(MonitorHandler.waiters))

class Application(tornado.web.Application):
	def __init__(self):
		handlers = [
			('/', MonitorHandler)
		]
		super(Application, self).__init__(handlers)

def main():
	app = Application()
	app.listen(8888)
	t = threading.Thread(target=vmstat)
	t.daemon = True
	t.start()
	print('Starting the server...')
	tornado.ioloop.IOLoop.instance().start()


if __name__ == '__main__':
	main()

树莓派 报IP 和 lcd显示IP

接 16x2 LCD

网上找的,就属这张图清晰了。lc_wire.png2013-07-18 13.05.08.jpg2013-07-18 17.48.54.jpg

准备

由于我使用的是pidora, 所以很多库默认都没装(貌似是没wheezy方便,不过习惯了centos)


播放声音本想用mpc的,但安装完总有问题,于是就编译了一个 madplay

yum -y install alsa-utils alsa-lib-devel

至于TTS嘛,木有,就自己从网上下载了几段,然后拼起来播放。屏幕快照 2013-08-06 下午2.04.54.png

for i in {0..255}; do wget -O $i.mp3 http://tts-api.com/tts.mp3?q=$i; done

实现代码

#!/usr/bin/env python
# encoding: utf-8

import Adafruit_CharLCD
import subprocess, time, datetime, math, signal, sys, os

def get_ip(device):
	ip = subprocess.check_output("ip -4 addr show " + device + " | grep inet | awk '{print $2}' | cut -d/ -f1", shell = True).strip()
	return ip

def main():
	last_ip = ip = ''
	maxLen = 16
	while True:
		ip = get_ip('eth0')
		if ip == last_ip:
			time.sleep(10)
			continue
		last_ip = ip
		sounds = ' /root/Music/tts/dot.mp3 '.join(['/root/Music/tts/' + i + '.mp3' for i in last_ip.split('.')]).split(' ')
		spaceLen = maxLen - len(ip)
		ip = int(math.floor(spaceLen / 2)) * ' ' + ip
		lcd.clear()
		lcd.message('  Raspberry Pi  \n')
		lcd.message(ip)
		subprocess.call(['madplay', '/root/Music/tts/your_ip_address_is.mp3'] + sounds)
		time.sleep(10)
		# + chr(0xdf) + 'C'
		# while True:
		# 	time.sleep(1)
		# 	lcd.clear()
		# 	lcd.message(datetime.datetime.now().strftime('  %I : %M : %S \n%a %b %d %Y'))

def onShutdown(sig, id):
	lcd.clear()
	time.sleep(.1)
	sys.exit(0)

if __name__ == '__main__':
	pid = os.fork()
	if pid == 0:
		signal.signal(signal.SIGTERM, onShutdown)
		lcd = Adafruit_CharLCD.Adafruit_CharLCD()
		main()
	else:
		sys.exit(0)

mac代理黑名单设置的问题

mac下启用代理的时候,发现设置的黑名单无效

屏幕快照 2013-07-24 上午10.02.53.png

貌似在中文版下面使用的是顿号,将顿号改为英文的逗号,设置就会生效,不过下次再改的时候,系统又会自动给你改成顿号,每次保存都需要手动修改。

[Laravel4] 短网址之统计每日点击数

使用redis计数,laravel4里面默认使用的是predis,这里我使用的是phpredis库,首先注释掉app/config/app.php里面的Redis的alias

// 'Redis'           => 'Illuminate\Support\Facades\Redis',

实现代码

使用redis的sorted set储存每日的每个链接的点击次数

$config = Config::get('database.redis.default');
with($redis = new Redis)->connect($config['host'], $config['port']);
$redis->zIncrBy(date('Ym:d'), 1, $link->id);

统计数据,取出当天点击数最多的10个链接的id

$redis->zRevRange(date('Ym:d'), 0, 9);

[Laravel4] 短网址之API

我们提供三种格式的API, txt json jsonp

代码

路由

Route::get('short.txt', 'ShortController@txt');
Route::get('short.json', 'ShortController@json');
Route::get('short.jsonp', 'ShortController@jsonp');

控制器

public function txt() {
	$validator = Validator::make(Input::all(), [
				'url' => 'required|max:255|url',
			]);
	if ($validator->fails()) {
		return implode(PHP_EOL, $validator->errors()->all());
	}
	$url = Input::get('url');
	$hash = md5($url);
	$link = Link::whereHash($hash)->first();
	if (!$link)
		$link = Link::create(compact('url', 'hash'));
	$shorten = \Lib\Base62::encode($link->id);
	return 'http://usr.im/' . $shorten;
}

public function json() {
	$resp = [];
	$validator = Validator::make(Input::all(), [
				'url' => 'required|max:255|url',
			]);
	if ($validator->fails()) {
		return ['status' => 'failed', 'message' => $validator->errors()->all()];
	}
	$url = Input::get('url');
	$hash = md5($url);
	$link = Link::whereHash($hash)->first();
	if (!$link)
		$link = Link::create(compact('url', 'hash'));
	$shorten = \Lib\Base62::encode($link->id);
	return ['status' => 'success', 'content' => 'http://usr.im/' . $shorten];
}

public function jsonp() {
	$resp = [];
	Validator::extend('callback', function($attribute, $value, $parameters) {
		return preg_match('/^[A-z_]\w*$/i', $value);
	});
	$validator = Validator::make(Input::all(), [
				'url' => 'required|max:255|url',
				'callback' => 'required|max:255|callback',
			]);
	if ($validator->fails()) {
		return Response::json(['status' => 'failed', 'message' => $validator->errors()->all()])
						->setCallback(Input::get('callback'));
	}
	$url = Input::get('url');
	$hash = md5($url);
	$link = Link::whereHash($hash)->first();
	if (!$link)
		$link = Link::create(compact('url', 'hash'));
	$shorten = \Lib\Base62::encode($link->id);
	return Response::json(['status' => 'success', 'content' => 'http://usr.im/' . $shorten])
					->setCallback(Input::get('callback'));
}

Windows8修改账户目录

Windows8下的用户目录如果为中文名,可能会造成某些软件不能正常使用。

开启Administrator账户

计算机(右键) - 管理 - 本地用户和组 - 用户QQ截图20130528214826.png

更改目录名称和注册表

使用Administrator账户登录,修改 /Users/[中文] 为 /Users/[English],若遇到文件夹正在被使用的情况可以使用procexp查出进程并结束。QQ截图20130528214657.png

修改注册表, Win + r , regedit

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Profilelist
// 找到下面的 ProfileImagePath 修改成上面刚改过的英文路径。

设置权限

/Users/[English] (右键)- 安全 - (选中用户)编辑QQ截图20130528220300.png

至此全部搞定。

cython将python转换为c

选择

之前使用过pyinstaller打包python程序,但是遇到读取相对路径下的配置文件的问题,而且这些只是预编译成python的2进制码。

选择cython和pyinstaller的原因主要考虑的是批量部署的方便性。cython能直接将python翻译成c,然后编译,在安全性上有了一定的保障。

安装cython

选择最简单的安装方法,使用pip包管理

pip install cython
# 在网上找的一个脚本,感觉很好用的,这里直接编译成可执行程序
mkcython.sh -e main.py

mkcython.sh.zip

pygments生成图片中的中文

先上图片:preview.png

非要中英文都有的字体么

说实话,原生的“中英文都有的”字体,都不是很适合用来显示代码。而网上有个雅黑和consolas的混合字体,但感觉对字体的依赖性比较大

pygments有个好处,就是本来就支持高亮的结果存为图片,于是要对其进行修改,让他用不用的字体来渲染中文和英文。

code = '''
#!/usr/bin/env python
# encoding: utf-8

from pygments import highlight
from pygments.lexers import PythonLexer
from pygments.formatters import ImageFormatter
# 可以有中文么a可以的
code = ""
content = highlight(code, PythonLexer(), ImageFormatter(font_name = 'WenQuanYi Zen Hei'))
with open('a.png', 'wb') as handle:
	handle.write(content)
	handle.close()
'''.decode('utf-8')
# content = highlight(code, PythonLexer(), ImageFormatter(font_name = 'Consolas', line_numbers = False, font_size = 20))
content = highlight(code, PythonLexer(), ImageFormatter(font_name = 'Consolas', cfont_name = 'Microsoft Yahei', line_numbers = False, font_size = 20, cfont_size = 13))
with open('a.png', 'wb') as handle:
	handle.write(content)
	handle.close()

我修改了一下image的生成,在原来的基础上加了两个参数cfont_name, cfont_size

原理就是分离出中文,然后使用中文字体渲染,而英文使用英文字体渲染。

[Laravel4] 实战之短网址

数据库表结构

CREATE TABLE `u_links` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `url` varchar(255) NOT NULL DEFAULT '',
  `hash` varchar(32) NOT NULL,
  `hits` int(10) unsigned NOT NULL DEFAULT '0',
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `hash` (`hash`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

虽然理论上url可以很长,但是这里约束一下255

目录结构

这里仅列出需要动到的目录和文件

app/config             配置文件目录
app/controllers        控制器
app/models             模型
app/views              视图
app/lib                自己建的,方便放一些公用库
app/routes.php         路由

代码

对于短网址的算法不再说明,网上很多,这里使用base62来处理

配置文件

app/config/app.php

  1. 打开debug
  2. 修改时区为'Asia/Shanghai'
  3. 修改key,可使用artisan生成php artisan key:generate

app/config/database.php

  1. 修改mysql的配置

定路由

// 显示首页
Route::get('/', 'HomeController@index');
// 网址转向
Route::get('{shorten}', 'HomeController@redirect')
	->where('shorten', '[0-9A-z]+');
// 网址点击统计
Route::get('{shorten}!', 'HomeController@show')
	->where('shorten', '[0-9A-z]+');

控制器

由于HomeController本身就存在,所以我们不需要生成或新建。 这里我们会用到base62的库,附件中会给出QQ20130519-2.png

贴代码:

public function index() {
	$shorten = '';
	$url = Input::get('url');
	if (!is_null($url)) {
		$validator = Validator::make(compact('url'), [
				'url' => 'required|max:255|url',
			]);
		if ($validator->fails())
			return Redirect::to('/')->withInput()->withErrors($validator->errors());
		$hash = md5($url);
		$link = Link::whereHash($hash)->first();
		if (!$link)
			$link = Link::create(compact('url', 'hash'));
		$shorten = \Lib\Base62::encode($link->id);
	}
	return View::make('home.index')
				->with(compact('url', 'shorten'));
}
public function redirect($shorten) {
	$id = \Lib\Base62::decode($shorten);
	$link = Link::find($id);
	if ($link) {
		$link->increment('hits');
		return Redirect::to($link->url, 301);
	}
	App::abort(404);
}
public function show($shorten) {
	$id = \Lib\Base62::decode($shorten);
	$link = Link::find($id);
	if ($link) {
		return View::make('home.show')
					->with($link->toArray());
	}
	App::abort(404);
}

Base62.zip

[Laravel4] 安装

安装composer

# 由于使用的MAMP,指定php
export PATH=/Applications/MAMP/bin/php/php5.4.10/bin:$PATH

mkdir /Applications/composer
cd /Applications/composer

curl -sS https://getcomposer.org/installer | php
mv composer{.phar,}
# PATH加路径
vi ~/.zshrc
# :/Applications/composer
. ~/.zshrc

安装laravel4

# 用git://没成功,可能是公司端口的原因
git clone -b develop https://github.com/laravel/laravel.git l4
cd l4
composer install

2013/06/22 22:37更新

不加--prefer-dist的话安装下来有100多M

composer create-project laravel/laravel . --prefer-dist

phantomjs中文问题

我在centos上安装的phantomjs,然后截图的时候,中文不显示,于是安装中文字体,最后貌似没有任何反映;于是又搜到网上说要安装所有的字体`yum -y install *-fonts-*`,安装完之后貌似是好了,但是中文的大小不一很难看,于是我又删掉了这些字体;最后发现只要安装了Arial字体就正常了。

# 拷贝字体到 /usr/share/fonts 或者 在下面建立一个目录(便于管理)
mkfontscale
mkfontdir
fc-cache -fv

至此,中文的问题就没了。但貌似效果还是没有mac或者pc上面的好。