2017年6月22日 星期四

pi3 UART by python

#!/usr/bin/env python
import serial

ser = serial.Serial(
  port='/dev/ttyAMA0',
  baudrate = 9600,
  parity=serial.PARITY_NONE,
  stopbits=serial.STOPBITS_ONE,
  bytesize=serial.EIGHTBITS,
  timeout=1
)

print "Serial is open: " + str(ser.isOpen())

print "Now Writing"
ser.write("This is a test")

print "Did write, now read"
x = ser.readline()
print "got '" + x + "'"

ser.close()

port='/dev/ttyAMA0'
 console=/dev/ttyS0,115200 

pi3 nodejs UART socket IO

http://samselectronicsprojects.blogspot.tw/2012/11/nodejs-raspberry-pi-serial.html

serialport = require("serialport").SerialPort;

/**
 * Serial Port Setup.
 */

var portName = '/dev/ttyAMA0'; //This is the standard Raspberry Pi Serial port
var readData = ''; //Array to hold the values read in from the port

var sp = new serialport(portName, {
  baudRate: 9600,
  dataBits: 8,
  parity: 'none',
  stopBits: 1,
  flowControl: false
});

/**
 * Server Code
 */

var server = http.createServer(app).listen(app.get('port'), function(){
  console.log("Express server listening on port " + app.get('port'));
});

var io = require('socket.io').listen(server);

io.sockets.on('connection', function(socket){
console.log("Socket connected"); 
socket.emit('connected', 123);
  });
  
  /*
 * GET home page.
 */
var fs = require('fs')

exports.index = function(req, res){
  res.writeHead(200, {'Content-Type': 'text/html'});
  var contents = fs.readFileSync("./public/index.html", "UTF-8");
  res.end(contents);
//res.render('index');

}

var socket = io.connect('http://your ip address here..');

    socket.on('connected', function(data) {
      console.log('Connected, this is what I received : ', data);
      //you could then emit something here for the server to receive like socket.emit("blah", "helloworld") -hello world is a string of data you are passing the sever here..
    });

socket.on('sendSerial', function(data) {
console.log("Client sent us: " + data + "to send to serial");
    sp.write(mbBuffer, function (err, bytesWritten) {
    console.log('bytes written:', bytesWritten);
}); 

sp.on('data', function (data) {
    console.log(data);
    data = data.toString();
    socket.emit('receiveSerial', data);
}); 

sp.on('close', function (err) {
console.log('port closed');
});

sp.on('error', function (err) {
console.error("error", err);
});

sp.on('open', function () {
console.log('port opened...');
});

//============================================ 
//APP.JS

/**
 * Module dependencies.
 */

var express = require('express')
  , routes = require('./routes')
  , user = require('./routes/user')
  , http = require('http')
  , path = require('path')
  , serialport = require("serialport").SerialPort;

/**
 * Serial Port Setup.
 */

var portName = '/dev/ttyAMA0'; //This is the standard Raspberry Pi Serial port

var readData = ''; //Array to hold the values read in from the port

var sp = new serialport(portName, {
  baudRate: 9600,
  dataBits: 8,
  parity: 'none',
  stopBits: 1,
  flowControl: false
});

/**

 * Express Setup.
 */

var app = express();

app.configure(function(){
  app.set('port', process.env.PORT || 80);
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.favicon());
  app.use(express.logger('dev'));
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
  app.use(express.static(path.join(__dirname, 'public')));
});

app.configure('development', function(){
  app.use(express.errorHandler());
});

app.get('/', routes.index);
app.get('/users', user.list);

/**
 * Actual Server Code
 */

var server = http.createServer(app).listen(app.get('port'), function(){
  console.log("Express server listening on port " + app.get('port'));
});

var io = require('socket.io').listen(server);

  /**
 * Server and socket started, below are all my listeners and emitters
 */

io.sockets.on('connection', function(socket){
  console.log("Socket connected"); 
  socket.emit('connected', 123);

  socket.on('sendSerial', function(data) {
    console.log("Client sent us: " + data + "to send to serial");
    sp.write(mbBuffer, function (err, bytesWritten) {
      console.log('bytes written:', bytesWritten);
    });
  });

  sp.on('data', function (data) {
    console.log(data);
    var mbRec = new Buffer(data, 'utf')
    console.log(mbRec);
    mbRec = mbRec.toString('hex');
    console.log(mbRec);
    socket.emit('serialEvent', mbRec);
  });

  sp.on('close', function (err) {
    console.log('port closed');
  });

  sp.on('error', function (err) {
    console.error("error", err);
  });

  sp.on('open', function () {
    console.log('port opened...');
  });
});

//==============================================
/*
 * GET home page.
 */
var fs = require('fs')

exports.index = function(req, res){
  res.writeHead(200, {'Content-Type': 'text/html'});
  var contents = fs.readFileSync("./public/index.html", "UTF-8");
  res.end(contents);
//  res.render('index');
};

ALL Hypriot Docker LIST

https://hub.docker.com/u/hypriot/?page=2

hypriot/rpi-whoami
hypriot/rpi-busybox-httpd
hypriot/rpi-alpine-scratch
hypriot/rpi-mysql
hypriot/armhf-hello-world
hypriot/rpi-haproxy
hypriot/rpi-dockerui
hypriot/rpi-traefik
hypriot/rpi-node
hypriot/rpi-portainer
hypriot/rpi-java
hypriot/armhf-busybox
hypriot/rpi-redis
hypriot/rpi-python
hypriot/rpi-consul
hypriot/rpi-gogs-raspbian
hypriot/rpi-swarm
hypriot/rpi-gogs-alpine
hypriot/rpi-influxdb
hypriot/rpi-iojs
hypriot/rpi-noip
hypriot/rpi-golang
hypriot/rpi-alpine
hypriot/rpi-nano-httpd
hypriot/whoami
hypriot/rpi-ruby
hypriot/image-builder
hypriot/rpi-crate
hypriot/rpi-gpio
hypriot/rpi-google-coder
hypriot/rpi-registrator
hypriot/rpi-hugo
hypriot/qemu-register
hypriot/rpi-dirtycow
hypriot/rpi-drone
hypriot/wiringpi
hypriot/rpi-tor-relay
hypriot/rpi-consul-template
hypriot/armhf-unshare
hypriot/arm-pyinstaller
hypriot/rpi-skydns
hypriot/skydns


Docker-swarm 控制多網路區域的 Docker

http://www.ithome.com.tw/guest-post/99967

Docker在1.9版有了大進展,從單機架構跨入多主機架構,關鍵就是原生網路支援和Docker-Swarm叢集功能正式釋出,但要怎麼用呢?請看一手協助時間軸科技開發團隊導入Docker,用一行腳本指令就能快速建立整套開發環境的專家來告訴你

Docker在1.9版有了大進展,從單機架構跨入多主機架構,關鍵就是原生網路支援和Docker-Swarm叢集功能正式釋出,但要怎麼用呢?請看一手協助時間軸科技開發團隊導入Docker,用一行腳本指令就能快速建立整套開發環境的專家來告訴你
最新的 Docker 1.9.0 在 11 月份正式推出,且多了 Network 的設置,剛開始看到時似乎沒什麼新奇,在社群上看到相關的文章,在一開始 docker-swarm 在官方網站用的是 local 的環境來進行展示,參考:Install and Create a Docker Swarm。

其實已經很方便了,但尚未可以透過 docker-compose 讓設置方式一目了然,畢竟是多環境的架構,若有沒有一個很好的配置檔,在維護上將會讓人卻步,且在 docker 之間的溝通,若是不屬於同一個網域的 docker,很多地方需要手動處理。

而在 network 的出現,docker-swarm 總算可以更進一步成為維運人員的神兵利器:

透過 docker-machine 來控制多台 docker engine
透過 docker-swarm 來整合多台 docker engine 資源
透過 docker-compose 來配置多個 docker 之間的溝通
著實是一個重要的里程碑,個人認為是非常夢幻的組合!

本文章將針對如何搭配 network 利用 docker-swarm 控制多網路區域的 Docker 進行說明。

參考資料
get started: Docker overlay network
Docker multi host networking
Docker swarm with Consul
Consul 搭配 Docker 之架構
使用 Consul 主要的目的是讓可能運行在不同雲端或是不在同一個網域的 Docker 可以知道彼此的位置,其架構圖如下:



如上圖所示,我們需要建置:

Consul Key Store daemon
Docker Swarm master
Docker Swarm node
過程中透過 docker-machine 來建立相關的 docker engine,並且透過 Swarm master 來分派每個 docker container 要執行的節點。

設置 Consul key-value store
第一步驟,我們需要建立 Consul Key Store daemon,透過下列指令。

docker-machine create -d virtualbox mh-keystore

接著,我們可以透過

eval "$(docker-machine env mh-keystore)"

讓 docker-machine 把 docker engine 控制權切換到 mh-keystore。

mh-keystore 的 docker engine 將會提供相關資訊給 cluster node 之 docker engine 以便後續控制,下面是讀取設定得語法:

docker-machine config mh-keystore

將會輸出下面資料

--tlsverify
--tlscacert="/Users/spooky/.docker/machine/certs/ca.pem" --tlscert="/Users/spooky/.docker/machine/certs/cert.pem" --tlskey="/Users/spooky/.docker/machine/certs/key.pem"
-H=tcp://192.168.99.103:2376%
透過上面的內容,我們需要建立 consul docker 並且啟動

docker $(docker-machine config mh-keystore) run -d \  
    -p "8500:8500" \
    -h "consul" \
    progrium/consul -server -bootstrap
建立 cluster node 之 docker engine
為了展示,我們需要建立兩個節點,分別如下:

swarm master
docker-machine create \  
-d virtualbox \
--swarm --swarm-image="swarm" --swarm-master \
--swarm-discovery="consul://$(docker-machine ip mh-keystore):8500" \
--engine-opt="cluster-store=consul://$(docker-machine ip mh-keystore):8500" \
--engine-opt="cluster-advertise=eth1:2376" \
mhs-demo0  
相關屬性說明

--swarm-master: 指定此 docker engine 為主要 swarm 節點。
--swarm-discovery: 告訴 swarm 節點,可以去哪裡查看控管的節點。
--cluster-store: 告訴 docker engine 在 overlay network 底下 key-value store 所在位置。
--cluster-advertise: 則當 docker machine 建立 docker engine 時連帶 public cluster network 以便外部可以存取。
swarm node
docker-machine create -d virtualbox \  
--swarm --swarm-image="swarm:1.0.0" \
--swarm-discovery="consul://$(docker-machine ip mh-keystore):8500" \
--engine-opt="cluster-store=consul://$(docker-machine ip mh-keystore):8500" \
--engine-opt="cluster-advertise=eth1:2376" \
mhs-demo1  
除了 --swarm-master 這 option 沒有之外其他都跟 swarm master 相同,運作上,一旦 swarm node 建立之後就會在 mh-keystore 進行註冊,而 swarm master 要進行資源分配時也會透過 mh-keystore 來了解目前所有節點的連接方式,以便後續進行處理。

有了 Consul 的協助,才能讓 swarm 的監控立於 local 之上,對 多網路區域 進行控管。

建立完成後,再透過 docker-machine ls 查看一下目前有的 machine 有哪些,顯示如下:

NAME          ACTIVE   DRIVER       STATE     URL                         SWARM  
mh-keystore   -        virtualbox   Running   tcp://192.168.99.103:2376  
mhs-demo0     *        virtualbox   Running   tcp://192.168.99.104:2376   mhs-demo0 (master)  
mhs-demo1     -        virtualbox   Running   tcp://192.168.99.105:2376   mhs-demo0  
切換到 swarm master 節點,並且加上 --swarm 參數:

eval $(docker-machine env --swarm mhs-demo0)

如此我們可以透過 swarm master 知道各節點的狀況,在執行 docker info 取的下面資訊:

Containers: 3  
Images: 2  
Role: primary  
Strategy: spread  
Filters: health, port, dependency, affinity, constraint  
Nodes: 2  
 mhs-demo0: 192.168.99.104:2376
  └ Containers: 2
  └ Reserved CPUs: 0 / 1
  └ Reserved Memory: 0 B / 1.021 GiB
  └ Labels: executiondriver=native-0.2, kernelversion=4.1.12-boot2docker, operatingsystem=Boot2Docker 1.9.0 (TCL 6.4); master : 16e4a2a - Tue Nov  3 19:49:22 UTC 2015, provider=virtualbox, storagedriver=aufs
 mhs-demo1: 192.168.99.105:2376
  └ Containers: 1
  └ Reserved CPUs: 0 / 1
  └ Reserved Memory: 0 B / 1.021 GiB
  └ Labels: executiondriver=native-0.2, kernelversion=4.1.12-boot2docker, operatingsystem=Boot2Docker 1.9.0 (TCL 6.4); master : 16e4a2a - Tue Nov  3 19:49:22 UTC 2015, provider=virtualbox, storagedriver=aufs
CPUs: 2  
Total Memory: 2.043 GiB  
Name: ca37a455e055  
現在我們所在 docker-machine 是 swarm master,因此我們可以建立 overlay network,透過下面指令:

docker network create --driver overlay my-net

如此既使此 swarm 叢集下的節點不在同一個 host 也可以透過 overlay network 來進行 docker 間的溝通。

透過 docker network ls 來查詢目前 network 的配置,結果如下:

NETWORK ID          NAME                DRIVER  
0c12ded9133d        my-net              overlay  
398d539735a5        mhs-demo0/host      host  
69c46465440e        mhs-demo0/bridge    bridge  
60fb35d0f1b9        mhs-demo0/none      null  
3d307d5ce727        mhs-demo1/bridge    bridge  
063bc7f3af71        mhs-demo1/none      null  
7439c6e27aa9        mhs-demo1/host      host  
開始運行 docker
我們需要建立 client server 的架構來驗證運作狀況,首先我們需要 ...

建立 web server 使用 nginx
指令如下:

docker run -itd --name=web --net=my-net --env="constraint:node==mhs-demo0" nginx

該指令透過 --env="constraint:node==mhs-demo0" 來控制 docker 要建立的節點設為 mhs-demo0

透過 --net=my-net 來指定要建立在哪一個 network。

接著我們需要 ...

建立 client 對 web 進行 request
指令如下:

docker run -it --rm --net=my-net --env="constraint:node==mhs-demo1" busybox wget -O- http://web

跟 web server 類似,透過 --env="constraint:node==mhs-demo1" 來控制 docker 要建立的節點為 mhs-demo1。

設置在同一個 network 以便兩者可以進行溝通,另外因為 server 已有命名為 web 我們可以透過 http://web 來進行 request。

執行結果如下

Connecting to web (10.0.0.2:80)  
<!DOCTYPE html>  
<html>  
<head>  
<title>Welcome to nginx!</title>  
<style>  
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>  
</head>  
<body>  
<h1>Welcome to nginx!</h1>  
<p>If you see this page, the nginx web server is successfully installed and  
working. Further configuration is required.</p>

<p>For online documentation and support please refer to  
<a href="http://nginx.org/">nginx.org</a>.<br/>  
Commercial support is available at  
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>  
</body>  
</html>  
-                    100% |*******************************|   612   0:00:00 ETA
我們可以透過 docker ps 來查看一下目前 docker 的狀況

CONTAINER ID        IMAGE   COMMAND                  STATUS                   PORTS            NAMES  
175be1c1bab0        busybox "wget -O- http://web"    Exited (0) 9 seconds ago                  mhs-demo1/busybox  
ea02022ce6fb        nginx   "nginx -g 'daemon off"   Up 2 minutes             80/tcp, 443/tcp  mhs-demo0/web  
可以看到從 NAMES 中可以清楚看到兩個 docker 分別跑在不同的 node 上,但彼此間溝通是沒有問題的。

使用 docker-compose 進行操作
設定檔如下

web:

  image: bfirsh/compose-mongodb-demo
  environment:
      - "MONGO_HOST=dockeradvancebook_mongo_1"
      - "constraint:node==mhs-demo0"
  ports:
      - "80:5000"
mongo:  
  image: mongo
docker-compose --x-networking --x-network-driver overlay up -d

啟動完成後,再次透過 docker ps 來確認狀況,結果如下:

IMAGE                         COMMAND                PORTS                        NAMES  
mongo                         "/entrypoint.sh mongo" 27017/tcp                    mhs-demo1/dockeradvancebook_mongo_1  
bfirsh/compose-mongodb-demo   "/bin/sh -c 'python a" 192.168.99.104:80->5000/tcp  mhs-demo0/dockeradvancebook_web_1  
如此就完成整個 demo,可以透過 http://192.168.99.104 存取執行結果。

結論
上述的 demo 雖然是在 VirtualBox 完成,但實際上可以整合多個機台的環境或是多個 cloud provider 進行 docker 部署,比如 azure + digitalocean。

透過 Consul 跟 Docker 最新特性 network 的幫忙,讓 Swarm 的控制可以立於 overlay network ,使 Docker 部署更方便之外,也讓配置更加容易。