Last active
December 19, 2015 16:19
-
-
Save gnue/5983381 to your computer and use it in GitHub Desktop.
富士通BSC F-PLUG から温度・湿度・照度・消費電力を取出すための実証コード
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# -*- coding: utf-8 -*- | |
require 'rubygems' | |
require 'serialport' | |
class Fplug | |
DEFAULT_PORT = '/dev/tty.fplug' | |
REQ_TEMPLATE = [0x10, 0x81, 0x00, 0x00, 0x0e, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x62, 0x01, 0x00, 0x00] | |
INFO_TYPES = { | |
temp: {classcode: 0x11, epc1: 0xe0, unit: '℃', scale: 0.1}, # 温度 | |
humid: {classcode: 0x12, epc1: 0xe0, unit: '%', scale: 1}, # 湿度 | |
illum: {classcode: 0x0D, epc1: 0xe0, unit: 'lx', scale: 1}, # 照度 | |
rwatt: {classcode: 0x22, epc1: 0xe2, unit: 'W', scale: 0.1}, # 消費電力 | |
} | |
class << INFO_TYPES | |
INDEXES = {} | |
def make_index(key) | |
index = {} | |
self.each_value { |type| index[type[key]] = type } | |
index | |
end | |
def find_by_key(value, key) | |
INDEXES[key] ||= make_index(key) | |
INDEXES[key][value] | |
end | |
end | |
def self.open(port = nil) | |
fplug = new(port) | |
yield fplug | |
rescue | |
ensure | |
fplug.close | |
end | |
def initialize(port = nil) | |
port ||= DEFAULT_PORT | |
@sp = SerialPort.new(port, 9600, 8, 1, SerialPort::NONE) # 9600bps, 8bit, ストップビット1, パリティ無し | |
@tid = 0 | |
end | |
def close | |
@sp.close | |
end | |
def responce_clear | |
begin | |
@sp.read_nonblock(256) | |
rescue | |
end | |
end | |
def send(kind) | |
type = INFO_TYPES[kind.downcase] | |
req = REQ_TEMPLATE.dup | |
req[8], req[12] = type[:classcode], type[:epc1] | |
@req = req.pack('C*') | |
@req[2..3] = [@tid += 1].pack('v') # TID(トランザクションID) | |
@sp.write @req | |
end | |
# データを符号付整数で取出す(実機のエンディアンに非依存) | |
def signed_int(data, bytes) | |
case bytes | |
when 1 | |
format = 'c' | |
when 2 | |
format = 'v' | |
signed = 's' | |
when 4 | |
format = 'V' | |
signed = 'i' | |
end | |
return unless format | |
a = data.unpack(format) | |
a = a.pack(signed.upcase).unpack(signed) if signed | |
a.first | |
end | |
def receive | |
buf = @sp.read(1) + @sp.read_nonblock(255) | |
r = buf[0..13].unpack('C*') | |
seoj1, seoj2 = r[4..5] | |
esv, opc, epc1, pdc1 = r[10..13] | |
return unless esv == 0x72 && 0 < pdc1 | |
value = signed_int(buf[14, pdc1], pdc1) | |
type = INFO_TYPES.find_by_key(seoj2, :classcode) | |
return [nil, nil] unless type | |
[value * type[:scale], type[:unit]] | |
end | |
def read(types = [:temp, :humid, :illum, :rwatt]) | |
data = {} | |
types.each { |kind| | |
responce_clear | |
send kind | |
value, unit = receive | |
data[kind] = value | |
} | |
data | |
end | |
end | |
if $0 == __FILE__ | |
port = ARGV.shift | |
def num_to_s(v) | |
v.kind_of?(Float) ? sprintf("%.1f", v) : v.to_s | |
end | |
def ltsv(data) | |
data.map { |k, v| "#{k}:#{num_to_s v}" }.join("\t") | |
end | |
def tsv(data) | |
data.map { |k, v| num_to_s(v) }.join("\t") | |
end | |
def format(data) | |
data.each { |key, value| | |
type = Fplug::INFO_TYPES[key] | |
next unless type | |
printf("%6s: %7.1f%s\n", key, value, type[:unit]) | |
} | |
end | |
Fplug.open(port) { |fplug| | |
data = {time: Time.now} | |
data.merge! fplug.read | |
# わかりやすく表示 | |
#format(data) | |
# LTSV出力 | |
#puts ltsv(data) | |
# TSV出力 | |
puts tsv(data) | |
} | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment