NumberBankしよっとね
https://gyazo.com/2dc08ddc0c45b129b9ee1fd3508f13bc
NumberBank
Scratch間で数字をやり取りする拡張機能
ブロック一覧
https://gyazo.com/ba4a5869357bb1671c7f606f5e793b69
NumberBankのシステム構成
https://scrapbox.io/files/66beb539e6c5bb001c87f8d6.svg
ScratchとNumberBankは、keyに割り当てられた設定情報をNumberBank and Firebase mapper(仮)から取得してを接続する
NumberBankの使い方
keyを設定する[マスター(key)をセット]ブロック
デフォルトのkeyでも利用可能(遅延が大きい)
登録すると、自分のデータベースも利用可能
データ書き込み
[(バンク)の(カード)を(10)にする]ブロックなどを使って、データベースに値を書き込む
データ読み出し
((バンク)の(カード)の値)ブロックを使って特定のデータを読み出す
非同期データ転送
[(バンク)の(カード)の更新確認を(入)にする]ブロックで更新確認を開始する
データが更新されたとき[更新されたとき]にイベントが渡される
2024/08/04現在、[更新された時]イベントブロックは動作していないような気がする
例:数字データのやり取り
ここで利用したマスターキーkeyはデフォルトで提供されているもの
バンクbank610t、カードcard610tでデータをやり取り
上矢印で乱数を書き込み
下矢印で乱数を読み込み
本来は、書き込みと読み込み部分のコードは別Scratchで動かす
緑の旗部分のコードは共通
https://gyazo.com/5dd650aa5fd22f2d37cb38167bf1d90f
NumberBankのデータ構造
ハッシュ(SHA256)を多用したデータ構造
bankコレクション
ドキュメント名bank_nameのSHA256
code:bank.json
{
'bank_name': bankの名前
'timestamp': データが入力された時間
}
https://gyazo.com/86697e706dccbe986b083d5fc6424d0a
cardコレクション
ドキュメント名uni_key: bankの名前とcardの名前の文字列を結合しSHA256を取ったもの
code:card.json
{
'number': 実際の数値データ
'timestamp': データが入力された時間
'bank_key': bank名のSHA256
'card_key': card名のSHA256
'master_key': master_keyから計算されたSHA256(ダミー値でも利用可能だった)
}
https://gyazo.com/280bfe0b6704336db0245e094ffec75a
Scratch外とのデータのやり取り
Firestore Databaseにアクセスできる言語ならなんでも可能
Python, Node.js, Java, C++, Go, ...
データの操作
読み出し
cardコレクションから読み出し可能
uni_keyドキュメントからデータを読み込む
code:read.py
uni_key= bank_key.strip()+card_key.strip()
uni_sha256=hashlib.sha256(uni_key.encode()).hexdigest()
ref_card = db.collection(u'card').document(uni_sha256)
データは、ref_cardを辞書として扱った時のnumberに入っている
code:read.py
dict=ref_card.get().to_dict()
書き込み
適切にデータ構造を設定して書き込み
bankには、以下のデータを書き込む
bank_name: bank_key(文字列)
time_stamp: 現在の時刻(使っていない?)
code:write.py
now=time.time()
# Data
bank_data={
'bank_name':bank_key,
'time_stamp':now,
}
# Write to database
db.collection("bank").document(bank_sha256).set(bank_data)
card(uni_keyのSHA256(uni_sha256))には、以下のデータを書き込む
bank_key: bank_keyのSHA256(bank_sha256)
card_key: card_keyのSHA256(card_sha256)
master_key: ダミーで大丈夫
number: 実際の数字データ
time_stamp: 現在の時刻(使っていない?)
code:write.py
# Keys & timestamp
bank_sha256=hashlib.sha256(bank_key.encode()).hexdigest()
card_sha256=hashlib.sha256(card_key.encode()).hexdigest()
uni_key= bank_key.strip()+card_key.strip()
uni_sha256=hashlib.sha256(uni_key.encode()).hexdigest()
now=time.time()
# Random data
num=random.randrange(9999)
# Data
card_data={
'bank_key':bank_sha256,
'card_key':card_sha256,
'master_key': 'dummy',
'number':num,
'time_stamp':now,
}
# Write to database
db.collection("card").document(uni_sha256).set(card_data)
デモ:数字のやり取り
https://gyazo.com/eb0a639f9aa3416c7d54178f29f19e51
数字読み込みスクリプトread.pyでは、argv[1]にbankの名前を、argv[2]にcardの名前を指定する
$ python read.py bank_test card_test
code:read.py
# For firebase
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore
import sys # ARGV
import hashlib # SHA256
cred = credentials.Certificate('secret_key.json')
app = firebase_admin.initialize_app(cred)
db = firestore.client()
bank_sha256=hashlib.sha256(bank_key.encode()).hexdigest()
card_sha256=hashlib.sha256(card_key.encode()).hexdigest()
uni_key= bank_key.strip()+card_key.strip()
uni_sha256=hashlib.sha256(uni_key.encode()).hexdigest()
ref_card = db.collection(u'card').document(uni_sha256)
dict=ref_card.get().to_dict()
print(dict)
print("Number:",num)
数字書き込みスクリプトwrite.pyはargv[3]を与えない場合、0-9999の乱数を書き込む
$ python write.py bank_test card_test
$ python write.py bank_test card_test 610
code:write.py
# For firebase
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore
import sys # ARGV
import random # Random data
import hashlib # SHA256
import time # Timestamp
cred = credentials.Certificate('secret_key.json')
app = firebase_admin.initialize_app(cred)
db = firestore.client()
bank_sha256=hashlib.sha256(bank_key.encode()).hexdigest()
card_sha256=hashlib.sha256(card_key.encode()).hexdigest()
print(len(sys.argv))
if(len(sys.argv)>3):
else:
num=random.randrange(9999)
print("Data:", num)
uni_key= bank_key.strip()+card_key.strip()
uni_sha256=hashlib.sha256(uni_key.encode()).hexdigest()
now=time.time()
bank_data={
'bank_name':bank_key,
'time_stamp':now,
}
db.collection("bank").document(bank_sha256).set(bank_data)
card_data={
'bank_key':bank_sha256,
'card_key':card_sha256,
'master_key': 'dummy',
'number':num,
'time_stamp':now,
}
db.collection("card").document(uni_sha256).set(card_data)
デモ:文字列のやり取り
https://gyazo.com/0ba3dc178ff8498116bb274185bc6f4b
card名str{数字}にtableリストで定義した独自文字コードを一文字づつ入れる
Python -> Scratch
code:send_str.py
# For firebase
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore
import sys # ARGV
import hashlib # SHA256
import time # Timestamp
# Global variables
now=time.time()
bank_key='string'
# Create Database handle
cred = credentials.Certificate('secret_key.json')
app = firebase_admin.initialize_app(cred)
db = firestore.client()
def write_data(i,c):
card_key="str"+str(i)
card_sha256=hashlib.sha256(card_key.encode()).hexdigest()
uni_key= bank_key.strip()+card_key.strip()
uni_sha256=hashlib.sha256(uni_key.encode()).hexdigest()
# Write data
card_data={
'bank_key':bank_sha256,
'card_key':card_sha256,
'master_key': 'dummy',
'number':ord(c)-ord('a')+1,
'time_stamp':now,
}
db.collection("card").document(uni_sha256).set(card_data)
# Write bank data
bank_sha256=hashlib.sha256(bank_key.encode()).hexdigest()
bank_data={
'bank_name':bank_key,
'time_stamp':now,
}
db.collection("bank").document(bank_sha256).set(bank_data)
# Write card data
i=1
for c in list(msg):
write_data(i,c)
i=i+1
write_data(i,chr(ord('a')-1)) # NULL terminate
https://gyazo.com/5d1ec7420b26010be90e1a8f2879f03c
Scratch -> Python
https://gyazo.com/46431ba9e8952164462a2ea1a19baea2
code:receive_str.py
# For firebase
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore
import hashlib # SHA256
# Global variables
bank_key='string'
# Create Database handle
cred = credentials.Certificate('secret_key.json')
app = firebase_admin.initialize_app(cred)
db = firestore.client()
# Read card data
i=1
num=-1
result=""
while (num!=0):
card_key="str"+str(i)
card_sha256=hashlib.sha256(card_key.encode()).hexdigest()
uni_key= bank_key.strip()+card_key.strip()
uni_sha256=hashlib.sha256(uni_key.encode()).hexdigest()
ref_card = db.collection(u'card').document(uni_sha256)
dict=ref_card.get().to_dict()
if(num!=0):
result=result+chr(num+ord('a')-1)
i=i+1
print(result)
おわりに
Stretch3(Scratch)のNumberBankを使ってみました
外部のPythonスクリプトとのデータのやり取りを紹介しました
Scratchどうしの数字データのやり取りだけではなく、外部システムとのやり取りができるのは面白いと思います