前五篇露水

讀取 RFID 資料的實驗
2016 年 9 月 23 日 (星期五) 01:30

剛買了 PN532 的實驗板,用 USB-TTL 的轉接器接駁到電腦上,再寫了以下簡單的 Python 程式去讀取附送的 MIFARE tag 的資料。輸入的資料格式及內容需參考 PN532 的說明書。由於我只花了很少時間寫以下程式,所以都沒留下什麼說明。

IMG_6969

import serial
from functools import reduce

def _uint8_add(a, b):
	"""Add add two values as unsigned 8-bit values."""
	return ((a & 0xFF) + (b & 0xFF)) & 0xFF

def lcs(length):
	return _uint8_add(~length, 1)

def dcs(data):
	return ~reduce(_uint8_add, data, 0xFF)& 0xFF
	
def read():
	result = []
	length = 0
	# hardcode 12 for reading the bytes
	for i in range(0, 12):
		currentByte = ser.read(1)
		result.append(currentByte)
		# position 9 is the length
		if i == 9:
			length = int(currentByte.encode('hex'), 16)
	for i in range(0, length + 1):
		currentByte = ser.read(1)
		result.append(currentByte)
	return result

def wakeup():
	ser.write([ 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
def write(data):
	length = len(data)
	ser.write([0x00, 0x00, 0xFF, length, lcs(length)] + data  + [dcs(data), 0x00])
def printByteArray(data):
	print [elem.encode("hex") for elem in data]

# open port with speed 115200
ser = serial.Serial('COM3', 115200, timeout=5)
print("opened {0}" . format(ser.name))
	
# wake up 
wakeup()
write([0xD4,0x14,0x01])
result = read()
printByteArray(result)

# get firmware version
write([0xD4,0x02])
result = read()
printByteArray(result)

# get card info
write([0xD4,0x4A,0x01,0x00])
result = read()
printByteArray(result)

以下是程式執行效果,當有 MIFARE tag 靠近實驗板的時候,就會讀到 MIFARE tag 的資料,然後程式就會完成執行:
Capture-rfid



參考資料:
NXP NFC Controller Solutions
PN532 Adafruit_Python_PN532
PN532

回應 (0)
將「Ten Types of Innovation」的要點套用到「Business Model Canvas」
2016 年 9 月 21 日 (星期三) 00:27

10types-bmc

Product Performance & Product System -> Value Propositions
Service -> Customer Relationships & Key Partners
Channel & Network -> Channels
Process -> Key Activities
Profit/Value Model -> Cost Structure/Revenue Streams
Structure -> Key Resources
Consumer Engagement -> Customer Segments & Customer Relationships
Brand -> Customer Relationships & Value Proposition

資料來源:
Which Innovation Framework do you use, the 10 types of innovation or the business model canvas?
Slideshare - Which Innovation Framework do you use, the 10 types of innovation or the business model canvas?
Quora - Can you link ten types of innovation to business model canvas? How?

回應 (0)
試玩 Ethereum
2016 年 9 月 13 日 (星期二) 00:07

在伺服器上裝了 geth 去試用「本機版」的 Ethereum (可說是支援合約的 Bitcoin)。

當然,「本機版」挖掘出來的都不是市場流通的 Ethereum,只用來做實驗。

果然可以在戶口之間進行交易,遲一點試下在上面寫合約程式。 Capture-ethereum-test

回應 (0)
計算將港鐵車程拆開以減低車費的車程組合
2016 年 8 月 22 日 (星期一) 13:54

注意:
本人並不確保本文的準確性,對任何損失或傷害概不負責,亦非鼓吹這樣做,只為作出簡單的計算供參考。本文提及的車費於本文刊登日有效。

眾所周知,如果在某些港鐵站前往羅湖或落馬洲,在上水出閘再原站入閘,總車費有可能會減少。我嘗試利用以下的小程式,計算出成人車票,包括八達通及單程車票,在港鐵系統內有可能因中途出閘再入閘而便宜了的組合。

先到政府資料一線通網站下載最新的港鐵車費表 mtr_lines_fares.csv(不包括輕鐵)。

再執行以下程式:
#!/usr/bin/env python

import csv
from math import ceil

octopusFareList = {}
ticketFareList = {}
stationList = {}
"""
	field available
	"SRC_STATION_NAME",
	"SRC_STATION_ID",
	"DEST_STATION_NAME",
	"DEST_STATION_ID",
	"OCT_ADT_FARE",
	"OCT_STD_FARE",
	"SINGLE_ADT_FARE",
	"OCT_CON_CHILD_FARE",
	"OCT_CON_ELDERLY_FARE",
	"OCT_CON_PWD_FARE",
	"SINGLE_CON_CHILD_FARE",
	"SINGLE_CON_ELDERLY_FARE"
"""
with open('mtr_lines_fares.csv', 'rb') as csvfile:
    reader = csv.DictReader(csvfile, delimiter=',')
    for row in reader:
		if (row['SRC_STATION_ID'] == row['DEST_STATION_ID']):
			continue
		srcId = int(row['SRC_STATION_ID'])
		destId = int(row['DEST_STATION_ID'])

		octopusFareList[srcId,destId] = float(row['OCT_ADT_FARE'])
		ticketFareList[srcId,destId] = float(row['SINGLE_ADT_FARE'])
		stationList[srcId] = row["SRC_STATION_NAME"]

# print octopusFareList[100,22]

# 1 = Central, 39 = Hong Kong , 3 = TST ,80 = ETST ,exclude these cases
centralStdId = 1
hongKongStdId = 39
tstStdId = 3
etstStdId = 80

print '"TYPE","START","OUT_AND_IN","END","OLD","NEW","SAVE"'
for i in range(1,121):
	for j in range(1,121):
		if i == j or (i == centralStdId and j == hongKongStdId) or (i == hongKongStdId and j == centralStdId) or (i == etstStdId and j == tstStdId)or (i == tstStdId and j == etstStdId):
			continue
		if (i,j) not in octopusFareList.keys():
			continue
		for x in range(1,121):
			if x == i or x == j or (i == centralStdId and x == hongKongStdId) or (i == hongKongStdId and x == centralStdId) or (i == etstStdId and x == tstStdId)or (i == tstStdId and x == etstStdId) or (j == centralStdId and x == hongKongStdId) or (j == hongKongStdId and x == centralStdId) or (j == etstStdId and x == tstStdId)or (j == tstStdId and x == etstStdId):
				continue
			if (i,x) not in octopusFareList.keys():
				continue
			if (x,j) not in octopusFareList.keys():
				continue
			# normal octopus case
			newOctupusFare = octopusFareList[i,x] + octopusFareList[x,j]
			if newOctupusFare <= octopusFareList[i,j] - 0.01:
				print '"OCTOPUS","' + stationList[i] + '","' + stationList[x] + '","' + stationList[j] + '",' + str(octopusFareList[i,j]) + "," + str(newOctupusFare) + "," + str(octopusFareList[i,j] - newOctupusFare)
			# 2nd trip discount
			newOctupusFare = octopusFareList[i,x] + ceil(octopusFareList[x,j] * 0.9*10.0)/10.0
			if newOctupusFare <= octopusFareList[i,j] - 0.01:
				print '"OCTOPUS(2nd trip)","' + stationList[i] + '","' + stationList[x] + '","' + stationList[j] + '",' + str(octopusFareList[i,j]) + "," + str(newOctupusFare) + "," + str(octopusFareList[i,j] - newOctupusFare)
			# single trip ticket
			newTicketFare = ticketFareList[i,x] + ticketFareList[x,j]
			if newTicketFare <= ticketFareList[i,j] - 0.01:
				print '"TICKET","' + stationList[i] + '","' + stationList[x] + '","' + stationList[j] + '",'+ str(ticketFareList[i,j]) + "," + str(newTicketFare) + ","  + str(ticketFareList[i,j] - newTicketFare)
		# Handle TST and ETST
		if (i != tstStdId) and (j != etstStdId) and (i != etstStdId) and (j != tstStdId):
			# normal octopus case
			newOctupusFare = octopusFareList[i,tstStdId] + octopusFareList[etstStdId,j]
			if newOctupusFare <= octopusFareList[i,j] - 0.01:
				print '"OCTOPUS","' + stationList[i] + '","' + stationList[tstStdId] + "->" + stationList[etstStdId] + '","' + stationList[j] + '",' + str(octopusFareList[i,j]) + "," + str(newOctupusFare) + "," + str(octopusFareList[i,j] - newOctupusFare)
			# 2nd trip discount
			newOctupusFare = octopusFareList[i,tstStdId] + ceil(octopusFareList[etstStdId,j] * 0.9*10.0)/10.0
			if newOctupusFare <= octopusFareList[i,j] - 0.01:
				print '"OCTOPUS(2nd trip)","' + stationList[i] + '","' + stationList[tstStdId] + "->" + stationList[etstStdId] + '","' + stationList[j] + '",' + str(octopusFareList[i,j]) + "," + str(newOctupusFare) + "," + str(octopusFareList[i,j] - newOctupusFare)
			# single trip ticket
			newTicketFare = ticketFareList[i,tstStdId] + ticketFareList[etstStdId,j]
			if newTicketFare <= ticketFareList[i,j] - 0.01:
				print '"TICKET","' + stationList[i] + '","' + stationList[tstStdId] + "->" + stationList[etstStdId] + '","' + stationList[j] + '",'+ str(ticketFareList[i,j]) + "," + str(newTicketFare) + ","  + str(ticketFareList[i,j] - newTicketFare)
		

			# normal octopus case
			newOctupusFare = octopusFareList[i,etstStdId] + octopusFareList[tstStdId,j]
			if newOctupusFare <= octopusFareList[i,j] - 0.01:
				print '"OCTOPUS","' + stationList[i] + '","' + stationList[etstStdId] + "->" + stationList[tstStdId] + '","' + stationList[j] + '",' + str(octopusFareList[i,j]) + "," + str(newOctupusFare) + "," + str(octopusFareList[i,j] - newOctupusFare)
			# 2nd trip discount
			newOctupusFare = octopusFareList[i,etstStdId] + ceil(octopusFareList[tstStdId,j] * 0.9*10.0)/10.0
			if newOctupusFare <= octopusFareList[i,j] - 0.01:
				print '"OCTOPUS(2nd trip)","' + stationList[i] + '","' + stationList[etstStdId] + "->" + stationList[tstStdId] + '","' + stationList[j] + '",' + str(octopusFareList[i,j]) + "," + str(newOctupusFare) + "," + str(octopusFareList[i,j] - newOctupusFare)
			# single trip ticket
			newTicketFare = ticketFareList[i,etstStdId] + ticketFareList[tstStdId,j]
			if newTicketFare <= ticketFareList[i,j] - 0.01:
				print '"TICKET","' + stationList[i] + '","' + stationList[etstStdId] + "->" + stationList[tstStdId] + '","' + stationList[j] + '",'+ str(ticketFareList[i,j]) + "," + str(newTicketFare) + ","  + str(ticketFareList[i,j] - newTicketFare)

執行後,可得出一萬多項結果。我將結果輸出到一個 csv file,可到下載。

以下為部分結果:
mtr-1

第一列為車票種類,有八達通、第二程八達通可享九折的車程(詳情)和單程車票。
第二列為起點車站,本例選取了大埔墟作為起點。
第三列為中途出閘再入閘(單程車票需重新購票)的車站。
第四列為終點車站。
第五及第六列分別為原來車費及新車費。
第七列為可節省的車費。

回應 (0)
RTL-SDR 筆記(16):將環狀天線訊號接入 FUNcube Dongle Pro+
2016 年 8 月 19 日 (星期五) 09:51

好一段日子之前買了這個主動式環狀天線,意圖接收波長比較長的短波和中波(一般數碼電視「手指」的短天線無法接收短波和中波),但因為它的輸出為 3.5mm 耳機頭,一直都未能接入自己的 RTL-SDR 或 FUNcube Dongle Pro+:
IMG_5816
IMG_5817

最近終於買了一系列轉接頭成功將訊號接入 FUNcube Dongle Pro+ 的 SMA 接頭,雖然明知有 impedance mismatch 和訊號損耗等問題,但總算叫做 proof-of-concept(想不到可以將音源線接入 SMA 頭):
IMG_6700

總算檢測到一些短波訊號(例如這個由泰國發射的電台),也聽得出有些人聲,但實在比較微弱,未算非常清晰,也未收到業餘電台:
IMG_6701
IMG_6698

內部連結:
【目錄】RTL-SDR 筆記

回應 (0)

前五篇露水
© 2002-2016 Harold Chan. 版權及聲明
counter