Akawa

ETY001的博客

这是这个系列的第二篇,主要讲一下各种设备接入配置。先放一张目前我已经配置好的管理界面图片

再放一张配置好的 HomeKit 截图

开始这篇之前,首先你要确保你已经安装了上一篇中提到的 SSH & Web Terminal 插件。

如何修改配置文件

如果已经安装好了 SSH & Web Terminal 插件并启动了,那么直接在 Terminal 中执行下面的命令就可以连接到树莓派上了。

1
ssh [email protected]

连接后 ,用 ls 查看目录

各个目录的作用如下:

  • addons 存储自定义插件
  • backup 备份目录
  • config 配置文件目录已经自定义组件
  • share 共享目录
  • ssl 证书目录

我们配置的时候,主要就是修改 config 目录下的 configuration.yaml 文件。每次修改保存后,要先在后台的“配置”=>“通用”中“检查配置”,配置检查通过后,再重载配置或者重启服务(有些配置的修改需要重启服务才能生效)。

接入小米多功能网关

打开 config/configuration.yaml,加入下面的配置(根据你的情况选择是多网关还是单网关配置):

1
2
3
4
5
6
7
8
9
10
11
12
# 使用单网关前提下,可不填 mac, mac 不带冒号
xiaomi_aqara:
gateways:
- mac:
key: xxxxxxxxxxxxxxxx
# 多个网关必须填入 mac,mac 不带冒号
xiaomi_aqara:
gateways:
- mac: xxxxxxxxxxxx
key: xxxxxxxxxxxxxxxx
- mac: xxxxxxxxxxxx
key: xxxxxxxxxxxxxxxx

其中 key 的获取,需要打开米家App,打开网关页面,点击右上角的三个点,打开菜单后,选择“关于”,之后“玩法教程”下面的空白处点击5次,就会出现新的列表选项,点击“局域网通信协议”,里面的密码就是 key 了,另外要把最上面的那个“局域网通信协议”的开关打开。

保存重启,接入网关成功后,通过网关接入的各种 ZigBee 设备都会被 HomeAssistant 识别出来。
目前的支持情况参见这里:https://home-assistant.cc/component/xiaomi/zigbee/

接入小米Wifi设备

插座类的配置如下:

1
2
3
4
5
switch:
- platform: xiaomi_miio
name: Original Xiaomi Mi Smart WiFi Socket
host: 192.168.130.59
token: YOUR_TOKEN

其中 name 可以自定义,host 是插座的IP地址,token则是通信用的凭证。

小米Wifi设备由于各个生产厂商的原因,并不像智能网关那么人性给提供设备的 token。获取 wifi 设备的 token 需要折腾一下。网上给出了几种方案,我使用的是用 Root 过的安卓手机。在手机上安装 5.0.19 版的米家(这是最后一个版本支持通过本地sqlite数据库查询 token 的版本),登陆米家,然后手机上打开文件管理器(比如ES文件管理器),把 /data/data/com.xiaomi.smarthome/databases/miio2.db 复制到电脑可访问的目录(比如SD卡),然后通过USB 把文件从手机转移到电脑上,用 sqlite 软件查询 devicerecord 表,其中有个 token 字段,那个就是了。

其他的一些Wifi设备参考这里:https://home-assistant.cc/component/xiaomi/wifi/

接入苹果HomeKit

配置这个的好处是,可以使用 Siri 来控制你的家庭智能场景和设备。

增加如下配置:

1
homekit:

保存重启服务后,会在主面板看到一个PIN码,这时候打开iPhone,找到 Home ,“添加配件”,“没有代码或无法扫描”,“输入代码”,把刚才的PIN码输入进去即可。

其他配置可参考这里:https://home-assistant.cc/homekit/builtin/

接入路由器

我的是网件路由刷的华硕的固件,因此找到华硕的配置如下:

1
2
3
4
5
6
7
8
asuswrt:
host: 路由器IP
username: 路由器账号
password: 路由器密码
protocol: 协议 ssh 或者 telnet
port: 端口,默认 22,telnet 模式为 23
mode: 模式,默认 router,可选 ap
ssh_key: ssh 秘钥路径,可选

其他路由参考:https://home-assistant.cc/component/router/

自定义组件

有时候,有些设备可能自带的组件并不支持,那么需要去搜索安装下第三方组件,比如小米直流电风扇,就需要去下载 https://github.com/syssi/xiaomi_fanconfig 目录下面,

然后按照第三方插件给的说明增加配置即可。

位置和天气设置

查询下经纬度,可以把经纬度设置好,之后就能显示当地的日落日出时间了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
homeassistant:
# 名称,可为中文
name: 家
# 纬度
latitude: !secret latitude
# 经度
longitude: !secret longitude
# 海拔
elevation: 11
# 度量单位,这里选择“米”
unit_system: metric
# 时区
time_zone: Asia/Shanghai
# 设备个性化
customize:

我使用的是yahoo天气的数据,配置如下:

1
2
3
4
weather:
- platform: ywether
woeid: 2168257
name: Zibo

其中 woeid 需要自己去 https://www.yahoo.com/news/weather/ 查询城市天气,URL中的id即为 woeid

个性化设置

个性化设置在 “配置” -> “自定义” 里面,在这里可以修改每个接入设备的名字等参数,并且可以设置是否隐藏(这个还是挺有用的,尤其是接入了路由器的情况下,会有很多的 device_tracker 类的设备,都显示在面板上显然是很乱的)。

一些可以参考的参数:https://home-assistant.cc/system/customize/

智能语言

配置这个的目的是为了能通过语音合成技术进行结果输出(播报)。

直接参考这里即可: https://home-assistant.cc/component/nlp/

结语

基本的配置就这些,目前家里所有的智能设备都加入到了 Home Assistant 的管理中了,之后就是配置各种智能逻辑了,等我试验过后,会在下一篇写一下。

Over!

本来今天应该是写(二)的,但是昨晚配置的过程中发现了很多问题,比如声音、蓝牙之类的配置,以及最关键的是发现原来 Hass.io 已经不被官方推荐了,现在官方推荐他们自己做的 HassOS,WTF,这都是啥跟啥?!所以今天就是把昨天写的(一)推翻掉,重新写。

先来说说刚才提到的 Hass.ioHassOS

按照目前我的理解,这个项目的演化历程是这样的,最早的 Home Assistant 是一堆脚本构成的,系统是基于 Respbian 的,所以起名叫做 Hassbian,之后基于 ResinOS(一个面向嵌入式系统的docker系统平台),把整个的核心代码封装进了两个镜像中,一个是 **homeassistant/raspberrypi3-homeassistant**,一个是 **homeassistant/armhf-hassio-supervisor**,其余的插件都各自独立成为一个镜像,这样整个系统运行起来就是一个 ResinOS 加上一堆容器,对于整体的稳定性和可维护性提升了不少,这也就是 Hass.io。再之后不知道什么原因,又基于 buildroot 系统(另外一个面向嵌入式的系统平台)做了 HassOS,这款比起上一款来说,感觉加入了一些新的驱动,比如声卡和蓝牙,另外就是宿主机做的更加的封闭了,可能是处于安全考虑,也可能是处于以后的商业考虑。

由于不想覆盖掉昨天的那篇,所以开始这篇作为第一篇,然后开始我们的重做系统之旅吧。。。。。

目前 HassOS 的稳定版本是 1.13,最新版本是 2.3,这个在 HassOS 项目的 Release 页面可以看到,https://github.com/home-assistant/hassos/releases 。我选择了 2.3 这个版本,由于我是树莓派3B,所以下载了 hassos_rpi3-2.3.img.gz 这个包(这里之所以不下载64位的是因为树莓派官方推出64位的系统时间也不长,稳定性有待观察)。

下载后解压得到 img 文件,依旧用 etcher 来写入到 TF 卡中。

这里需要注意,如果你是 Mac 电脑,那么写完后,会提示 TF 卡无法识别,你直接推出就好。这是因为 HassOS 使用的 GPT 分区格式,而 Mac 默认不支持这个格式。

那么这里就有意思了,往常都是 boot 分区是 FAT 格式,然后挂载,放入各种位置文件,比如wifi联网的配置,然后把卡插回树莓派,启动就能用了,但现在 TF 卡的 boot 分区无法挂载,这咋整?

官方给出了方案:https://github.com/home-assistant/hassos/blob/dev/Documentation/configuration.md ,思路就是再找一个U盘,格式化成 FAT32 / EXT4 / NTFS 任意格式,格式化的时候把U盘命名为 CONFIG(全大写)。

之后需要加入的配置文件,按照文档要求的格式放在U盘根目录下即可。启动树莓派的时候,先把U盘插好,系统会自动读取U盘的配置文件并生效。

另外注意就是配置network的时候,文件名必须是my-network。

除了网络配置以外,timesyncd.conf也要配置,否则系统启动起来时间不对,然后更新就会卡住,因为更新访问的是 HTTPS 加密链接,时间不对,签名就有问题,进而就无法访问更新镜像的链接(下面的截图就是这个坑了)。timesyncd.conf中的NTP服务器网上找下亚洲区的就好。

另外建议把 authorized_keys 也配置了吧,这样可以远程直接SSH到宿主机。authorized_keys 文件里的内容其实就是你电脑 ~/.ssh/id_rsa.pub 文件的内容,如果没有这个目录,就执行下 ssh-keygen 生成下。

还有就是一定记住,初始化结束后,要在UI界面上把U盘的配置再导入一次,这个之后会再提到,切记切记啊!!!

以上满满的都是坑!

所有工作做完,启动树莓派,来看看显示器最后输出的内容,默认登陆用户是root,不需要密码。

恩,你没有看错,登陆后是官方实现的一个 cli,用于便捷管理各种服务,屏蔽掉操作系统的存在。虽然现在允许你使用 login 命令进入宿主机,但是我觉得早晚会屏蔽掉这个命令,做的跟路由器似的。

这时候,你执行 login 进入宿主机,然后执行 docker ps,看看是不是一个 supervisor 的容器,一个 homeassistant/raspberrypi3-homeassistant 生成的容器。

如果没问题,那么在浏览器里访问 http://hassio.local:8123 就能看到创建新用户的界面了(如果你路由器不支持mDNS,那么就只能用 http://树莓派IP:8123 的形式访问了。

登陆之后,就能看到主界面了。去左边栏 Hass.io 中,选择 ADD-ON STORE,然后找到 SSH & Web Terminal,点进去安装,如下图

这个插件其实是让你 SSH 登陆进一个容器,然后把一些配置文件从宿主机映射进容器,这样相对安全一些。

安装完,在下面的配置中,把你的登陆用户名和密码加入进去,另外配置下 Web Terminal 的证书,证书是放在 /root/ssl 目录下的。你可以先关闭 Web Terminal,启动 SSH 成功后,用 SCP 把证书传上去,或者去插件中心安装 Samba Share 插件,用共享的方法传上去。

最关键的一步来了,在 Hass.io 中,选择 SYSTEM ,点击 IMPORT FROM USB 完成配置写入。

OK,这一篇就先到这里,下一篇真的要讲讲其他的配置了。

最近想要在树莓派上折腾下 Home Assistant。

Home Assistant 于 2017年7月26日发布的 Hass.io 集成系统,全可视化安装配置,基于 Docker 和 ResinOS。

Docker 的引入使得 Hass.io 管理功能插件就像你在手机上安装 App 一样简单(事实上 iOS 的底层确实采用了类似机制),再不用通过命令行和代码来管理你的 Home Assistant。同时,通过 Docker 来封装插件,使得插件的稳定性得到了极大提高,用户能够把精力集中在个性化定制 Home Assistant 及自动化上来。

可以预见 Hass.io 是 Home Assistant 的发展方向,如果说它有什么缺点的话,那么也在于它的封闭性上。

下载针对树莓派3的 hass.io 镜像

https://github.com/home-assistant/hassio-build/releases/

使用 etcher 写入镜像到 TF 卡

配置Wifi

如果树莓派采用 WiFi 连接,在烧录完成后使用文本编译器打开 TF 卡目录下 system-connections/resin-sample 文件,修改填写你的 WiFi 信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[connection]
id=resin-wifi
type=wifi

[wifi]
hidden=true
mode=infrastructure
ssid=你的 WiFi SSID

[ipv4]
method=auto

[ipv6]
addr-gen-mode=stable-privacy
method=auto

[wifi-security]
auth-alg=open
key-mgmt=wpa-psk
psk=你的 WiFi 密码

启动初始化

将 TF 卡插入树莓派中,上电,几分钟后,在浏览器(推荐 Chrome)地址栏输入 http://hassio.local:8123 即可看到如下界面了

由于没有国内的镜像站,所以且等着就好了,需要很久,除非你在路由上开了科学上网。

完成后,大致是这样

接下来

在下一篇将会继续安装相关的插件和配置,敬请期待。

跑路前还发个公告

重要公告
首先感谢大中华地区的BlockCDN爱好者和参与者,在这一年多来对BCDN项目的支持和鼓励。伴随BCDN走过了融资到退币,从94到成长。没有您们就没有BCDN的成长!为了更好的让分享型CDN能尽快的落地造福大众,区块链全球发展基金会(Blockchain Global Development Foundation)拟定同全球CDN巨头合作技术研发和加快BCDN的全球应用落地。具体洽谈合作商包括:Akamai 、 Amazon 、CloudFront、EdgeCast、CloudFlare。介于大中华地区对CDN的准入条件和对区块链行业的政策性风险,基金会艰难的决定暂停中国地区的BCDN业务和停止同原中国合作商(成都区块链公司)的开发和大中华区的推广合作。并于2018年12月1日起暂停原大中华区的BCDN挖矿,快照等一切活动。大中华区业务的从新开启时间待定。原大中华区平台内的BCDN资产请于12月15日前提现到个人ETH 钱包,官方将于12月15日24:00后将停止所有大中华区平台内BCDN的提现、维护等活动,未提现的按自愿放弃其所有权。望相互告知。再次感谢您的支持!

区块链全球发展基金会(Blockchain Global Development Foundation)
2018/11/22

之前写过一篇用 Portainer 图形界面工具来搭建 Docker 化的LNMP。但是每次开一台新的VPS,按照那个流程走下来都要累死,于是按照那个思路,整理了一份命令行版本的部署方案。

创建数据目录

1
mkdir -p /data/wwwroot && mkdir -p /data/logs && mkdir -p /data/mysql

这三个目录分别用来存储网站文件,网站日志,数据库文件。

在 CentOS 下安装 Docker

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine \
&& yum install -y yum-utils \
device-mapper-persistent-data \
lvm2 \
&& yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo \
&& yum install -y docker-ce \
&& systemctl enable docker \
&& systemctl start docker

以上是 Docker 官方给出的在 CentOS 下安装 Docker 的文档,Ubuntu 可以参考这里: https://docs.docker.com/install/linux/docker-ce/ubuntu/ 。在边栏还可以看到其他系统的安装方法。

创建子网络

1
docker network create --gateway "172.20.0.1" --subnet "172.20.0.0/16" lnmp

把 LNMP 放在独立的网络里更易管理。

部署 Nginx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
docker run -itd --name nginx nginx \
&& \
docker cp nginx:/etc/nginx /etc \
&& \
docker stop nginx && docker rm nginx \
&& \
docker run -itd --name nginx \
-v /etc/nginx:/etc/nginx \
-v /data/wwwroot:/data/wwwroot \
-v /data/logs/nginx:/var/log/nginx \
-p 80:80 -p 443:443 \
--restart always \
-l "ink.akawa.nginx" \
-v /tmp:/tmp \
--network lnmp --ip "172.20.0.2" nginx

前三行的作用就是启动一个临时的 Nginx 容器,目的是为了把其中的配置文件复制出来,最后再删除掉这个临时容器。最后一行就是真正启动 Nginx 容器的命令了。

部署 MySQL

1
read -s mysql_pass

输入MySQL管理员密码后,继续执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
docker run -itd --name mysql mariadb \
&& \
docker cp mysql:/etc/mysql /etc \
&& \
docker stop mysql && docker rm mysql \
&& \
docker run -itd --name mysql \
-p 3306:3306 \
-v /etc/mysql:/etc/mysql \
-v /data/mysql:/var/lib/mysql \
-v /tmp:/tmp \
-v /data/logs/mysql:/var/log/mysql \
--restart always \
--network lnmp \
--ip "172.20.0.3" \
-e MYSQL_ROOT_PASSWORD=$mysql_pass \
mariadb

前三行依旧是为了复制配置文件出来,第四行会要求你输入 MySQL 的 root 密码。第五行启动 MySQL 容器。

部署 PHP7

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
docker run -itd --name php7 ety001/php:7.2.14 \
&& \
docker cp php7:/etc/php7 /etc \
&& \
docker stop php7 && docker rm php7 \
&& \
docker run -itd --name php7 \
-v /etc/php7:/etc/php7 \
-v /data/wwwroot:/data/wwwroot \
-v /tmp:/tmp \
-v /data/logs/php7:/var/log/php7 \
--restart always \
--network lnmp \
--ip "172.20.0.4" \
ety001/php:7.2.14

前三行复制配置文件出来,第四行启动 PHP 容器。其中这里使用的镜像是我自己封装的,镜像里面写死了数据目录,如果你更改了数据目录,请自行修改 /etc/php7/php-fpm.d/www.conf 中的 chdir 参数值。

修改 Nginx 配置文件并进行测试

打开 /etc/nginx/conf.d/default.conf 文件,改成下面的样子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
server {
listen 80;
server_name localhost;

#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;

location / {
root /data/wwwroot/default; # <------ 修改这里为自己的目录
index index.html index.htm;
}

#error_page 404 /404.html;

# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}

# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
location ~ \.php$ {
root /data/wwwroot/default; # <------ 修改这里为自己的目录
fastcgi_pass 172.20.0.4:9000; # <------ 修改这里为正确的PHP解析地址
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; # <------ 修改这里的路径
include fastcgi_params;
}

# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}

修改好以后,执行 docker exec nginx nginx -s reload 重载 nginx 配置以使其生效。这时可以在 /data/wwwroot/default 目录下创建一个 index.html 的文件,然后浏览器访问下看看是否可以正常显示。再创建一个含有 <?php phpinfo();?> 代码的 PHP 文件测试下 PHP 是否可用。

后续要添加网站

后续如果要增加新的网站,只需要在 /data/wwwroot/ 中新建个文件夹存储网站文件,然后在 /etc/nginx/conf.d/ 中增加新网站的配置文件,最后执行 docker exec nginx nginx -s reload 重载 nginx 配置即可生效。

如果要增加 Let’s encrypted 的 SSL 的话,建议使用 acme.sh 中的 DNS 方法来注册证书,并把证书安装到 /etc/nginx/ssl 目录里,最后使用 docker restart nginx 来重启 Nginx 容器生效。这个后续可以再开篇文章写一下。

完工!

再来一篇,这篇代码是获取指定用户当前的 Voting Power,不废话直接上代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?php
function postData($data) {
$url = 'https://api.steemit.com';
$options = array(
'http' =>
array(
'header' => "Content-Type: application/json\r\n".
"Content-Length: ".strlen($data)."\r\n".
"User-Agent:SteemTools/1.0\r\n",
'method' => 'POST',
'content' => $data,
)
);
$context = stream_context_create($options);
try {
$result = file_get_contents($url, false, $context);
$r = json_decode($result, true);
$result = $r['result'];
} catch (\Exception $e) {
return false;
}
return $result;
}

function getAccountVotingPower($username) {
$data = postData('{"jsonrpc":"2.0", "method":"condenser_api.get_accounts", "params":[["'.trim($username).'"]], "id":1}');
$user = $data[0];
$last_vote_time = $user['last_vote_time'];
var_dump(strtotime($last_vote_time));
$voting_power = $user['voting_power'];
var_dump($voting_power);
$vpow = $voting_power + (10000 * (time() - strtotime($last_vote_time)) / 432000);
return number_format(min($vpow, 10000) / 100, 2);
}
var_dump(getAccountVotingPower('ety001'));

完工!

由于最近开发需要计算指定账号的赞的价值,因此研究了下。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<?php
function postData($data) {
$url = 'https://api.steemit.com';
$options = array(
'http' =>
array(
'header' => "Content-Type: application/json\r\n".
"Content-Length: ".strlen($data)."\r\n".
"User-Agent:SteemTools/1.0\r\n",
'method' => 'POST',
'content' => $data,
)
);
$context = stream_context_create($options);
try {
$result = file_get_contents($url, false, $context);
$r = json_decode($result, true);
$result = $r['result'];
} catch (\Exception $e) {
return false;
}
return $result;
}

function getRewardFund() {
$result = postData('{"id":0,"jsonrpc":"2.0","method":"call","params":["database_api","get_reward_fund",["post"]]}');
if (isset($result['reward_balance'])) {
$result['reward_balance'] = str_replace(' STEEM', '', $result['reward_balance']);
}
return $result;
}

function getAccountVests($username) {
$result = postData('{"jsonrpc":"2.0", "method":"condenser_api.get_accounts", "params":[["'.trim($username).'"]], "id":1}');
return str_replace(' VESTS', '', $result[0]['vesting_shares']) + str_replace(' VESTS', '', $result[0]['received_vesting_shares']) - str_replace(' VESTS', '', $result[0]['delegated_vesting_shares']);
}

function getCurrentMedianHistoryPrice() {
$result = postData('{"id":1,"jsonrpc":"2.0","method":"call","params":["database_api","get_current_median_history_price",[]]}');
return str_replace(' SBD', '', $result['base']) / str_replace(' STEEM', '', $result['quote']);
}

function getAccountUpvoteValue($username, $vp, $weight) {
$power = (100*$vp * 100*$weight / 1e4 + 49) / 50;
$total_vests = getAccountVests($username);
$final_vests = $total_vests * 1e6;
$rshares = $power * $final_vests / 1e4;
$rewards = getRewardFund();
$sbd_median_price = getCurrentMedianHistoryPrice();
$estimate = $rshares / $rewards['recent_claims'] * $rewards['reward_balance'] * $sbd_median_price;
return $estimate;
}

// var_dump(getRewardFund());
// var_dump(getAccountVests('ety001'));
// var_dump(getCurrentMedianHistoryPrice());
var_dump(getAccountUpvoteValue('ety001', 100, 100));

官网的公式已经很明确了,其中遇到的问题就是 voting powerweight 的精度问题了。由于在官网公式上并没有指明,所以很容易被忽略。

在我的代码中,很清楚的看到我传入的 voting power90weight100,由于 Steem 在百分比上的精度是下面这样子的:

1
100.00%

而存储在区块上的是整数 10000。因此官方给出的代码中,power = (voting_power * weight / 10000) / 50 要看你传入是什么精度的数据了。按照我的传参,我必须要给传入的值再乘以100才是正确结果,也就是我的代码是 $power = (100*$vp * 100*$weight / 1e4 + 49) / 50;。其中的 +49 是挺高精度的一种方式,可以去掉。

完工!

最近有个项目需要使用 eth 的智能合约,虽然我不看好eth,但是为了挣钱也不得不花些时间去学习下了。之所以选择 Docker 是因为我不喜欢删除的时候删不干净,毕竟不熟悉工具会安装哪些东西。使用 Docker 的话,基本上都被封装在容器里,不用了删掉容器和映射出来的目录数据就ok了。

去 eth 的 github 看了下,是有提供 Docker 镜像的,那么我们直接拉取官方做好的镜像包就好了

1
docker pull ethereum/client-go

由于我们是本地开发测试,所以我们启动测试节点

1
docker run -it --rm -v $(pwd)/eth:/root/.ethereum ethereum/client-go console --dev

其中 $(pwd)/eth 是用来存储区块数据的宿主机目录,设置成为自己的一个目录就好。
执行后,就会看到类似下面的样子

最后会出现一个 > 的控制符,这时候就可以输入命令了,比如查看下目前的账户

1
2
> eth.accounts
["0xeeffae8858bee06d1b4f57d7a2fbf3544a593f12"]

获取指定用户的 balance

1
2
> eth.getBalance(eth.accounts[0])
1.15792089237316195423570985008687907853269984665640564039457584007913129639927e+77

创建个密码是“ety001”的新用户来专门测试开发

1
2
> personal.newAccount('ety001')
"0x6ed051356a14c1354a95f3352856f05d622b1658"

转账给新账户,用于测试

1
> eth.sendTransaction({from: '0xb0ebe17ef0e96b5c525709c0a1ede347c66bd391', to: '0xf280facfd60d61f6fd3f88c9dee4fb90d0e11dfc', value: web3.toWei(1, "ether")})

从网上找一段合约代码试试创建合约,把下面的代码复制到 Remix 里,编译器选择 0.4.18 编译,之后点击“detail”

1
2
3
4
5
6
7
8
9
10
11
12
pragma solidity ^0.4.18;
contract hello {
string greeting;

function hello(string _greeting) public {
greeting = _greeting;
}

function say() constant public returns (string) {
return greeting;
}
}

点击“detail”打开一个浮层,里面找到 WEB3DEPLOY 的代码,复制出来,修改一下第一行,比如

1
var _greeting = 'hi, ety001'

修改完后解锁钱包,把代码复制进 console 里,回车,即可创建新的合约了

1
> personal.unlockAccount(eth.accounts[1],"ety001");

console 里输入 hello.say() 回车后,就能看到输出了 hi, ety001 了,这样一个智能合约的开发环境就搭建好了。

完工!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
function steem_per_mvests() {
$url = 'https://api.steemit.com';

$data = '{"jsonrpc":"2.0", "method":"database_api.get_dynamic_global_properties", "id":1}';
$options = array(
'http' =>
array(
'header' => "Content-Type: application/json\r\n".
"Content-Length: ".strlen($data)."\r\n".
"User-Agent:SteemMention/1.0\r\n",
'method' => 'POST',
'content' => $data,
)
);
$context = stream_context_create($options);
try {
$result = file_get_contents($url, false, $context);
$r = json_decode($result, true);
$result = $r['result'];
} catch (\Exception $e) {
return false;
}
return $result['total_vesting_fund_steem']['amount'] / ($result['total_vesting_shares']['amount'] / 1e6);
}

function vests_to_sp($vests) {
$steem_per_mvests = steem_per_mvests();
if ($steem_per_mvests) {
return $vests / 1e6 * $steem_per_mvests;
} else {
return false;
}
}

昨天刷机结束,成功root后,还没有来得及安装谷歌四件套,毕竟很多软件不敢从国内应用商店安装,有些软件则是国内应用商店没有的。

今天使用老方法,去 GoPlayCN 下载回App,然后安装,结果一直在 Google Play 服务那一步安装失败,于是又从网上搜了半天,最后发现正确的安装姿势应该是去 Open Gapps 下载卡刷包,然后进第三方Recovery 直接卡刷。在 Open Gapps 上只要选好自己的CPU是啥架构的,安卓版本是啥,选择什么体型的包,然后下载就ok啦~

0%