[update] micropython i2c I/O の一部に対応

This commit is contained in:
ocogeclub 2022-07-26 17:09:53 +09:00
parent 5cc7bb9662
commit 073bcd5d78
8 changed files with 1156 additions and 1752 deletions

View File

@ -102,35 +102,26 @@
<block type="controls_whileUntil"> <block type="controls_whileUntil">
<field name="MODE">WHILE</field> <field name="MODE">WHILE</field>
</block> </block>
<block type="ugj_control_for"> <block type="controls_for">
<field name="crease">+</field> <field name="VAR" id="oFFZ#D{*XbIVL=!W~X]w">番号</field>
<value name="index"> <value name="FROM">
<block type="variables_get">
<field name="VAR" id="CP-q*|4;)+PZj!ExWdjr">番号</field>
</block>
</value>
<value name="from">
<shadow type="math_number"> <shadow type="math_number">
<field name="NUM">1</field> <field name="NUM">1</field>
</shadow> </shadow>
</value> </value>
<value name="to"> <value name="TO">
<shadow type="math_number"> <shadow type="math_number">
<field name="NUM">10</field> <field name="NUM">10</field>
</shadow> </shadow>
</value> </value>
<value name="by"> <value name="BY">
<shadow type="math_number"> <shadow type="math_number">
<field name="NUM">1</field> <field name="NUM">1</field>
</shadow> </shadow>
</value> </value>
</block> </block>
<block type="ugj_controls_foreach"> <block type="controls_forEach">
<value name="item"> <field name="VAR" id="k4+0elF%?J]_)8fo((-m">項目</field>
<block type="variables_get">
<field name="VAR" id="}LJbKt^CxR.FJ6a3T23v">項目</field>
</block>
</value>
</block> </block>
<block type="controls_flow_statements"> <block type="controls_flow_statements">
<field name="FLOW">BREAK</field> <field name="FLOW">BREAK</field>
@ -352,7 +343,7 @@
<field name="level">1</field> <field name="level">1</field>
</block> </block>
<block type="ugj_gpio_set_input"> <block type="ugj_gpio_set_input">
<field name="lflag">_pi.PULL_DOWN</field> <field name="lflag">PULL_DOWN</field>
<value name="gpio"> <value name="gpio">
<shadow type="math_number"> <shadow type="math_number">
<field name="NUM">6</field> <field name="NUM">6</field>

View File

@ -76,6 +76,10 @@ var theme = Blockly.Theme.defineTheme('ocoge', {
// Customize messages // Customize messages
Blockly.Msg["CONTROLS_IF_MSG_THEN"] = "ならば"; Blockly.Msg["CONTROLS_IF_MSG_THEN"] = "ならば";
Blockly.Msg["CONTROLS_REPEAT_INPUT_DO"] = ""; Blockly.Msg["CONTROLS_REPEAT_INPUT_DO"] = "";
Blockly.Msg["CONTROLS_FOR_TITLE"] = "%1 を %2 から %3 まで %4 ずつ増やし(減らし)て";
Blockly.Msg["CONTROLS_FOR_TOOLTIP"] = "インデックス番号を決められた数ずつ増やし(減らし)ながら、ステートメントを実行します。";
Blockly.Msg["CONTROLS_FOREACH_TITLE"] = "リスト%2の各%1について";
Blockly.Msg["CONTROLS_FOREACH_TOOLTIP"] = "リストの各項目について、その項目を変数「項目」としてステートメントを実行します。";
Blockly.Msg["MATH_CHANGE_TITLE"] = "変数 %1 を %2 増やす"; Blockly.Msg["MATH_CHANGE_TITLE"] = "変数 %1 を %2 増やす";
Blockly.Msg["VARIABLES_SET"] = "変数 %1 を %2 にする"; Blockly.Msg["VARIABLES_SET"] = "変数 %1 を %2 にする";
// Blockly.Msg["TEXT_PRINT_TITLE"] = "ダイアログに %1 を表示"; // Blockly.Msg["TEXT_PRINT_TITLE"] = "ダイアログに %1 を表示";
@ -313,22 +317,9 @@ const ugj_loadWorkspace = () => {
} }
} }
// // Python コードフォーマッタ YAPF をコール
// const ugj_pyBeautify = (code) => {
// let formatted;
// formatted = window.ocogeapi.child_process.spawnSync('python3', ['-m', 'yapf'], { input: code }).stdout.toString();
// return formatted;
// }
// Python コードフォーマッタ Black をコール // Python コードフォーマッタ Black をコール
const ugj_pyBeautify = (code) => { const ugj_pyBeautify = (code) => {
let formatted = ''; let formatted = '';
// // formatted = window.ocogeapi.child_process.spawnSync('python3', ['-m', 'black', '-'], { input: code }).stdout.toString();
// try {
// formatted = require('child_process').spawnSync('python3', ['-m', 'black', '-'], { input: code }).stdout.toString();
// } catch (e) {
// formatted = code;
// console.log('Python formatter "Black" is not found.');
// }
formatted = require('child_process').spawnSync('python3', ['-m', 'black', '-'], { input: code }).stdout.toString(); formatted = require('child_process').spawnSync('python3', ['-m', 'black', '-'], { input: code }).stdout.toString();
if (!formatted) formatted = code; if (!formatted) formatted = code;
return formatted; return formatted;
@ -349,7 +340,6 @@ const ugj_createCode = (args) => {
window.alert('Python 非対応のブロックが使用されています。\n' + e.message); window.alert('Python 非対応のブロックが使用されています。\n' + e.message);
code = ''; code = '';
} }
// code = Blockly.Python.workspaceToCode(workspace);
} }
else { // Javascript コード出力 else { // Javascript コード出力
code = Blockly.JavaScript.workspaceToCode(workspace); code = Blockly.JavaScript.workspaceToCode(workspace);
@ -380,44 +370,6 @@ const ugj_createCode = (args) => {
} }
// ブロックスクリプト実行 // ブロックスクリプト実行
// var is_running = false;
// var worker;
// const ugj_runCode = async () => {
// const {
// Worker,
// isMainThread,
// setEnvironmentData,
// getEnvironmentData,
// } = require('worker_threads');
// const stop_icon = `<i class="fas fa-ban"></i> 停止`;
// const run_icon = `<i class="fas fa-play-circle"></i> 実行`;
// document.activeElement.blur(); //実行ボタンからフォーカスを外す:エンターキー押下が悪さをするため
// let btnel = document.getElementById('runbtn');
// if (is_running) {
// worker.terminate();
// } else {
// if (isMainThread) {
// btnel.innerHTML = stop_icon;
// let code = ugj_createCode({});
// setEnvironmentData('code', code);
// worker = new Worker(__filename);
// // worker.on('exit', (excode) => {
// // btnel.innerHTML = run_icon;
// // });
// // } else {
// // let AsyncFunction = Object.getPrototypeOf(async function () { }).constructor;
// // let ocogeFunc = new AsyncFunction(getEnvironmentData('code'));
// // await ocogeFunc().catch(e => { console.error(e); });
// }
// }
// is_running = !is_running;
// if (is_running) btnel.innerHTML = stop_icon;
// else btnel.innerHTML = run_icon;
// }
const ugj_runCode = async () => { const ugj_runCode = async () => {
if (elutil.lang == 'js') { if (elutil.lang == 'js') {
document.activeElement.blur(); //実行ボタンからフォーカスを外す:エンターキー押下が悪さをするため document.activeElement.blur(); //実行ボタンからフォーカスを外す:エンターキー押下が悪さをするため
@ -445,8 +397,8 @@ const ugj_spawnPyboard = (code, mode) => {
p.stderr.on('data', d => { console.error(d.toString()) }); p.stderr.on('data', d => { console.error(d.toString()) });
p.stdout.on('data', d => { console.log(d.toString()) }); p.stdout.on('data', d => { console.log(d.toString()) });
p.on('close', c => { p.on('close', c => {
if (c == 0) console.log(`正常終了`); if (c == 0) console.log(`コード実行 OK`);
else window.alert(`エラーが発生しました。詳しくはコンソールを参照してください。`); else _fukidashi(`実行時エラーが発生しました。詳しくはコンソールを参照してください。`, 5);
}); });
} }
@ -454,13 +406,11 @@ const ugj_spawnPyboard = (code, mode) => {
// エレメントのオブジェクトとかコールバックとか Python対応とか // エレメントのオブジェクトとかコールバックとか Python対応とか
// 色々この中で完結させてみる // 色々この中で完結させてみる
const ugj_showCode = () => { const ugj_showCode = () => {
// var ext = 'js';
var ext = elutil.lang; var ext = elutil.lang;
const dialog = document.getElementById('codeDlg'); const dialog = document.getElementById('codeDlg');
const content = document.getElementById('dlgContent'); const content = document.getElementById('dlgContent');
const btn_close = document.getElementById('dlgClose'); const btn_close = document.getElementById('dlgClose');
const btn_export = document.getElementById('dlgExport'); const btn_export = document.getElementById('dlgExport');
// const chkbox_cli = document.getElementById('dlgCli');
const dialog_title = document.getElementById('dlgTitle'); const dialog_title = document.getElementById('dlgTitle');
@ -484,7 +434,6 @@ const ugj_showCode = () => {
const export_cb = () => { const export_cb = () => {
if (ext == 'js') { if (ext == 'js') {
let code = ugj_createCode({ 'ext': ext, 'async': true, 'beautify': true }); let code = ugj_createCode({ 'ext': ext, 'async': true, 'beautify': true });
// if (elutil.saveFile(code, ext) === false) window.alert('保存できませんでした。');
save_to_file(code); save_to_file(code);
} else { } else {
let code = ugj_createCode({ 'ext': 'py', 'beautify': true }); let code = ugj_createCode({ 'ext': 'py', 'beautify': true });
@ -493,23 +442,18 @@ const ugj_showCode = () => {
close_cb(); close_cb();
} }
const keyev_cb = ev => { const keyev_cb = ev => {
if (ev.key == 'c' && ext == 'js') { if (ev.key == 's' && ev.ctrlKey) {
// CLI モード
// blackboardWrite()とwindow.alert()、fukidashi()をconsole.log()に書き換え、
// document... と ugj_... と elutil... をコメントアウト(ブラウザ関連部分の追放という意味では不完全なので注意)
// あと正規表現もいい加減
let code = ugj_createCode({ 'ext': ext, 'async': true, 'beautify': true }); let code = ugj_createCode({ 'ext': ext, 'async': true, 'beautify': true });
code = code.replace(/const appendDiv[^#]*\/\/#/gm, 'const blackboardWrite = text => console.log(text);').replace('window.alert', 'console.log').replace(/_fukidashi(.*), \d+(\);)/gm, 'console.log$1$2').replace(/(^(?=.*document.)[^;]*;)/gm, '/* $1 */').replace(/(^(?=.*ugj_)[^;]*;)/gm, '/* $1 */').replace(/(^(?=.*elutil.)[^;]*;)/gm, '/* $1 */'); if (ext == 'js') {
// if (elutil.saveFile(code, ext) === false) window.alert('保存できませんでした。'); // JS-CLI モード
save_to_file(code); // blackboardWrite()とwindow.alert()、fukidashi()をconsole.log()に書き換え、
close_cb(); // document... と ugj_... と elutil... をコメントアウト(ブラウザ関連部分の追放という意味では不完全なので注意)
} else if (ev.key == 'f' && ext == 'py') { // あと正規表現もいい加減
let code = ugj_createCode({ 'ext': ext, 'beautify': true }); code = code.replace(/const appendDiv[^#]*\/\/#/gm, 'const blackboardWrite = text => console.log(text);').replace('window.alert', 'console.log').replace(/_fukidashi(.*), \d+(\);)/gm, 'console.log$1$2').replace(/(^(?=.*document.)[^;]*;)/gm, '/* $1 */').replace(/(^(?=.*ugj_)[^;]*;)/gm, '/* $1 */').replace(/(^(?=.*elutil.)[^;]*;)/gm, '/* $1 */');
// if (elutil.saveFile(code, ext) === false) window.alert('保存できませんでした。'); }
save_to_file(code); save_to_file(code);
close_cb(); close_cb();
} }
} }
btn_close.addEventListener('click', close_cb); btn_close.addEventListener('click', close_cb);
btn_export.addEventListener('click', export_cb); btn_export.addEventListener('click', export_cb);

View File

@ -229,7 +229,7 @@ class elUtil {
filter = { name: 'text file', extensions: ['txt'] }; filter = { name: 'text file', extensions: ['txt'] };
} }
let filename = await this.ipcRenderer.invoke('save_dialog', title, defName, filter); let filename = await this.ipcRenderer.invoke('save_dialog', title, defName, filter);
this.doc_current = this.path.dirname(filename); if (filename) this.doc_current = this.path.dirname(filename);
return filename; return filename;
} }
// ファイル書き込み // ファイル書き込み

View File

@ -7,7 +7,16 @@ import os
import sys import sys
import pyboard import pyboard
import serial.tools.list_ports import serial.tools.list_ports
from tkinter import messagebox from tkinter import filedialog
##### 引数 #####
args = sys.argv
try:
dev = args[1]
except IndexError as err:
dev = False
else:
dev = (dev=='-f')
##### グローバル変数 ##### ##### グローバル変数 #####
gport = None gport = None
@ -16,118 +25,168 @@ gport = None
# リストボックスにドロップ # リストボックスにドロップ
def listbox_drop(event): def listbox_drop(event):
files = listbox.tk.splitlist(event.data) files = listbox.tk.splitlist(event.data)
for f in files: putfiles(files)
if os.path.exists(f): # キーボード
print('Dropped file: "%s"' % f)
if os.path.isfile(f):
putfile(f)
filelist()
else:
messagebox.showwarning('Warning', 'フォルダは転送できません')
else:
print('Not dropping file "%s": file does not exist.' % f)
def input_key(ev): def input_key(ev):
# print(ev)
if ev.keysym == 'F5': if ev.keysym == 'F5':
filelist() reload()
elif ev.keysym == 'Delete': elif ev.keysym == 'Delete':
selected = listbox.curselection() rmfiles()
for i in selected: # ダブルクリック
src = listbox.get(i) def dbl_click(ev):
call_pybfunc('fs_rm', src) run()
print('Deleted %s' % src) # 右クリックメニュー
if len(selected): def pop_menu(ev):
filelist() listbox.select_clear(0, END)
listbox.select_set(listbox.nearest(ev.y))
def on_closing(errmsg=''): pmenu.post(ev.x_root, ev.y_root)
if errmsg:
messagebox.showerror('Error', errmsg)
root.destroy()
sys.exit(0)
##### pyboard関数 ##### ##### pyboard関数 #####
# 接続・repl開始
def connect(): def connect():
global gport global gport
try: try:
pyb = pyboard.Pyboard(gport) pyb = pyboard.Pyboard(gport)
pyb.enter_raw_repl() except pyboard.PyboardError as err:
return pyb gport = None
except: listbox.delete(0, END)
on_closing('デバイスに接続できません') set_title('Lost device : Please reload')
raise pyboard.PyboardError('Lost device')
pyb.enter_raw_repl(False)
return pyb
# repl終了・切断
def disconnect(pyb): def disconnect(pyb):
try: try:
pyb.exit_raw_repl() pyb.exit_raw_repl()
pyb.close() except Exception as err:
except: pass
on_closing('切断に失敗しました')
# コマンド実行
def exec_command(cmd):
pyb = connect()
try: try:
retval = pyb.exec_(cmd) pyb.close()
except: except Exception as err:
on_closing('コマンド実行時にエラーが発生しました') pass
disconnect(pyb) # ファイル送信 (複数可)(files: list of local filepath)
return retval.decode('utf-8') def putfiles(files):
# pyboard.py の関数をコール
def call_pybfunc(funcname, *args):
pyb = connect() pyb = connect()
if funcname=='fs_put': for src in files:
pyb.fs_put(args[0], args[1]) if os.path.exists(src):
elif funcname=='fs_rm': if os.path.isfile(src):
pyb.fs_rm(args[0]) dest = os.path.basename(src)
print('ファイル "%s" を転送' % src)
pyb.fs_put(src, dest)
else:
print('フォルダは転送できません : %s' % src)
else:
print('ファイル "%s" は見つかりません。' % f)
ls(pyb)
disconnect(pyb) disconnect(pyb)
# ポートスキャン:アルファベット順で一番若いポートを返す
def initialize(): def find_device():
global gport global gport
for p in sorted(serial.tools.list_ports.comports()): for p in sorted(serial.tools.list_ports.comports()):
if p.hwid.startswith('USB'): if p.hwid.startswith('USB'):
gport = p.device gport = p.device
set_title(gport) set_title(gport)
filelist()
break break
else: else:
on_closing('デバイスがみつかりません') gport = None
set_title('No device')
def list_clear(): raise OSError('Device not found')
listbox.delete(0, END) # 再読込:ここのみデバイスの再スキャンが入る
def reload():
def filelist(): if not gport:
list_clear() find_device()
files = ls() if gport:
for f in files: listfiles()
listbox.insert(END, f) # ファイルリスト取得だけを行う
def listfiles():
def ls(src='/'): pyb = connect()
ls(pyb)
disconnect(pyb)
# ファイルリストを取得し、リストボックスに表示 (pyb: pyboard handle, src: target directory on device)
def ls(pyb, src='/'):
cmd = ( cmd = (
"import uos\nfor f in uos.listdir(%s):\n" "import uos\nfor f in uos.listdir(%s):\n"
" print(f)" " print(f)"
% (("'%s'" % src) if src else "") % (("'%s'" % src) if src else "")
) )
retval = exec_command(cmd) retval = pyb.exec(cmd)
return retval.splitlines() files = retval.decode('utf-8').splitlines()
listbox.delete(0, END)
def putfile(src): for f in files:
dest = os.path.basename(src) listbox.insert(END, f)
call_pybfunc('fs_put', src, dest) # ウィンドウタイトル (title: string)
def set_title(title): def set_title(title):
root.title('PyBfm - ' + title) root.title('PyBfm - ' + title)
# デバイス上のファイルを実行
def run(follow=False):
selected = listbox.curselection()
if len(selected):
src = listbox.get(selected[0])
ext = os.path.splitext(src)[1]
if ext == '.py':
cmd = 'exec(open("%s").read())' % src
pyb = connect()
try:
if follow:
print (pyb.exec(cmd).decode('utf-8'))
else:
pyb.exec_raw_no_follow(cmd)
except Exception as err:
print("Runtime error.")
print('Done.')
disconnect(pyb)
else:
print('このファイルは実行できません')
# ファイル選択ダイアログからファイル送信
def putdlg():
fpath = filedialog.askopenfilename()
if fpath:
putfiles([fpath])
# ファイル受信
def getfile():
selected = listbox.curselection()
if len(selected):
src = listbox.get(selected[0])
ext = os.path.splitext(src)[1]
dest = filedialog.asksaveasfilename(
initialfile=src,
defaultextension=ext,
filetypes=[('変更なし', ext), ('全てのファイル', '.*')]
)
if dest:
pyb = connect()
pyb.fs_get(src, dest)
disconnect(pyb)
# デバイス上のファイル削除(複数可)
def rmfiles():
selected = listbox.curselection()
if len(selected):
pyb = connect()
for i in selected:
src = listbox.get(i)
pyb.fs_rm(src)
print('Deleted %s' % src)
ls(pyb)
disconnect(pyb)
# 何もしない関数
def do_nothing():
pass
##### メイン ##### ##### メイン #####
# メインウィンドウの生成 # メインウィンドウの生成
root = TkinterDnD.Tk() root = TkinterDnD.Tk()
root.protocol("WM_DELETE_WINDOW", on_closing)
root.title('PyBfm') root.title('PyBfm')
root.geometry('400x300') root.geometry('400x300')
pmenu = Menu(root, tearoff=0)
pmenu.add_command(label="実行", command=run)
if dev:
pmenu.add_command(label="実行 (追跡)", command=lambda:run(True))
pmenu.add_command(label="送る", command=putdlg)
pmenu.add_command(label="取得", command=getfile)
pmenu.add_command(label="削除", command=rmfiles)
pmenu.add_command(label="再読込", command=reload)
pmenu.add_command(label="閉じる", command=do_nothing)
# root.config(bg='#cccccc') # root.config(bg='#cccccc')
# Frameウィジェットの生成 # Frameウィジェットの生成
frame = Frame(root) frame = Frame(root)
@ -136,6 +195,8 @@ listbox = Listbox(frame, selectmode=EXTENDED)
listbox.drop_target_register(DND_FILES) listbox.drop_target_register(DND_FILES)
listbox.dnd_bind('<<Drop>>', listbox_drop) listbox.dnd_bind('<<Drop>>', listbox_drop)
listbox.bind("<KeyPress>", input_key) listbox.bind("<KeyPress>", input_key)
listbox.bind("<Double-Button-1>", dbl_click)
listbox.bind("<Button-3>", pop_menu)
# スクロールバーの生成 # スクロールバーの生成
scroll = Scrollbar(frame, orient=VERTICAL) scroll = Scrollbar(frame, orient=VERTICAL)
listbox.configure(yscrollcommand=scroll.set) listbox.configure(yscrollcommand=scroll.set)
@ -145,6 +206,11 @@ frame.pack(expand=True,fill=BOTH)
listbox.pack(expand=True,fill=BOTH, side=LEFT) listbox.pack(expand=True,fill=BOTH, side=LEFT)
scroll.pack(side=RIGHT, fill=Y) scroll.pack(side=RIGHT, fill=Y)
initialize() try:
find_device()
except Exception as err:
pass
else:
listfiles()
root.mainloop() root.mainloop()

View File

@ -26,7 +26,7 @@ pyb.enter_raw_repl()
if mode == 'r': if mode == 'r':
print('Run code', flush=True) print('Run code', flush=True)
pyb.exec(src) pyb.exec_raw_no_follow(src)
elif mode == 'd': elif mode == 'd':
print('Deploy code', flush=True) print('Deploy code', flush=True)
pyb.exec("f=open('%s','wb')\nw=f.write" % dest) pyb.exec("f=open('%s','wb')\nw=f.write" % dest)
@ -43,3 +43,4 @@ elif mode == 'd':
pyb.exec("f.close()") pyb.exec("f.close()")
pyb.exit_raw_repl() pyb.exit_raw_repl()
pyb.close()

2248
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "ocoge", "name": "ocoge",
"version": "0.1.7", "version": "0.1.8",
"description": "ブロックベースビジュアルプログラム開発・実行環境", "description": "ブロックベースビジュアルプログラム開発・実行環境",
"main": "main.js", "main": "main.js",
"scripts": { "scripts": {
@ -22,9 +22,9 @@
}, },
"homepage": "https://git.ocoge.club/ocoge.club/ocoge#readme", "homepage": "https://git.ocoge.club/ocoge.club/ocoge#readme",
"devDependencies": { "devDependencies": {
"@electron-forge/cli": "^6.0.0-beta.64", "@electron-forge/cli": "^6.0.0-beta.65",
"@electron-forge/maker-deb": "^6.0.0-beta.64", "@electron-forge/maker-deb": "^6.0.0-beta.65",
"electron": "^19.0.8", "electron": "^19.0.9",
"electron-rebuild": "^3.2.8" "electron-rebuild": "^3.2.8"
}, },
"dependencies": { "dependencies": {
@ -32,8 +32,8 @@
"@tensorflow-models/blazeface": "^0.0.7", "@tensorflow-models/blazeface": "^0.0.7",
"@tensorflow-models/knn-classifier": "^1.2.4", "@tensorflow-models/knn-classifier": "^1.2.4",
"@tensorflow-models/mobilenet": "^2.1.0", "@tensorflow-models/mobilenet": "^2.1.0",
"@tensorflow/tfjs": "^3.18.0", "@tensorflow/tfjs": "^3.19.0",
"@tensorflow/tfjs-backend-wasm": "^3.18.0", "@tensorflow/tfjs-backend-wasm": "^3.19.0",
"axios": "^0.27.2", "axios": "^0.27.2",
"node-abi": "^3.22.0", "node-abi": "^3.22.0",
"nodemailer": "^6.7.7", "nodemailer": "^6.7.7",

View File

@ -1,101 +1,3 @@
/** Fix Basic Blocks ****************************************************************************************/
Blockly.Blocks['ugj_control_for'] = {
init: function () {
this.appendValueInput("index")
.setCheck("Variable");
this.appendValueInput("from")
.setCheck("Number")
.appendField("を");
this.appendValueInput("to")
.setCheck("Number")
.appendField("から");
this.appendValueInput("by")
.setCheck("Number")
.appendField("まで");
this.appendDummyInput()
.appendField("ずつ")
.appendField(new Blockly.FieldDropdown([["増やして", "+"], ["減らして", "-"]]), "crease");
this.appendStatementInput("do")
.setCheck(null);
this.setInputsInline(true);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setTooltip("インデックス番号を決められた数ずつ増やし(減らし)ながら、ステートメントを実行します。");
this.setHelpUrl("");
this.setStyle('loop_blocks');
}
};
Blockly.JavaScript['ugj_control_for'] = function (block) {
var value_index = Blockly.JavaScript.valueToCode(block, 'index', Blockly.JavaScript.ORDER_ATOMIC);
// var variable_index = Blockly.JavaScript.nameDB_.getName(block.getFieldValue('index'), Blockly.Variables.NAME_TYPE);
var value_from = Blockly.JavaScript.valueToCode(block, 'from', Blockly.JavaScript.ORDER_ATOMIC);
var value_to = Blockly.JavaScript.valueToCode(block, 'to', Blockly.JavaScript.ORDER_ATOMIC);
var value_by = Blockly.JavaScript.valueToCode(block, 'by', Blockly.JavaScript.ORDER_ATOMIC);
var dropdown_crease = block.getFieldValue('crease');
var statements_do = Blockly.JavaScript.statementToCode(block, 'do');
let daishou;
if (dropdown_crease == '+') { daishou = '<'; }
else { daishou = '>'; }
var code = [
`for (${value_index} = ${value_from}; ${value_index} ${daishou}= ${value_to}; ${value_index} ${dropdown_crease}= ${Math.abs(value_by)}) {`,
statements_do,
`}`,
''
].join('\n');
return code;
};
Blockly.Python['ugj_control_for'] = function (block) {
var variable_index = Blockly.Python.nameDB_.getName(block.getFieldValue('index'), Blockly.Variables.NAME_TYPE);
var value_from = Blockly.Python.valueToCode(block, 'from', Blockly.Python.ORDER_ATOMIC);
var value_to = Blockly.Python.valueToCode(block, 'to', Blockly.Python.ORDER_ATOMIC);
var value_by = Blockly.Python.valueToCode(block, 'by', Blockly.Python.ORDER_ATOMIC);
var dropdown_crease = block.getFieldValue('crease');
var statements_do = Blockly.Python.statementToCode(block, 'do');
if (statements_do === '') statements_do = ' pass';
if (dropdown_crease == '+') { value_by = Math.abs(value_by); value_to++; }
else { value_by = Math.abs(value_by) * (-1); value_to--; }
var code = [
`for ${variable_index} in range(${value_from}, ${value_to}, ${value_by}) :`,
statements_do,
''
].join('\n');
return code;
};
Blockly.Blocks['ugj_controls_foreach'] = {
init: function () {
this.appendValueInput("list")
.setCheck("Array")
.appendField("リスト");
this.appendValueInput("item")
.setCheck("Variable")
.appendField("の各");
this.appendDummyInput()
.appendField("について");
this.appendStatementInput("do")
.setCheck(null);
this.setInputsInline(true);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setTooltip("リストの各項目について、その項目の内容を変数「項目」に代入してステートメントを実行します。");
this.setHelpUrl("");
this.setStyle('loop_blocks');
}
};
Blockly.JavaScript['ugj_controls_foreach'] = function (block) {
var value_list = Blockly.JavaScript.valueToCode(block, 'list', Blockly.JavaScript.ORDER_ATOMIC);
var value_item = Blockly.JavaScript.valueToCode(block, 'item', Blockly.JavaScript.ORDER_ATOMIC);
var statements_do = Blockly.JavaScript.statementToCode(block, 'do');
var code = [
`for (let _index in ${value_list}) {`,
`${value_item} = ${value_list}[_index];`,
statements_do,
`}`,
''
].join('\n');
return code;
};
// Custom Color Picker // Custom Color Picker
Blockly.FieldColour.COLOURS = [ Blockly.FieldColour.COLOURS = [
'#ffffff', '#808000', '#ffff00', '#ff00ff', '#ff4500', '#ffffff', '#808000', '#ffff00', '#ff00ff', '#ff4500',
@ -193,6 +95,11 @@ Blockly.JavaScript['ugj_bintodec'] = function (block) {
var code = `parseInt (${value_bin}, 2)`; var code = `parseInt (${value_bin}, 2)`;
return [code, Blockly.JavaScript.ORDER_NONE]; return [code, Blockly.JavaScript.ORDER_NONE];
}; };
Blockly.Python['ugj_bintodec'] = function (block) {
var value_bin = Blockly.Python.valueToCode(block, 'bin', Blockly.Python.ORDER_ATOMIC);
var code = `int(${value_bin}, 2)`;
return [code, Blockly.Python.ORDER_NONE];
};
var ugjHextodecDefinition = { var ugjHextodecDefinition = {
"type": "ugj_hextodec", "type": "ugj_hextodec",
@ -254,7 +161,7 @@ Blockly.JavaScript['ugj_dectohex'] = function (block) {
}; };
Blockly.Python['ugj_dectohex'] = function (block) { Blockly.Python['ugj_dectohex'] = function (block) {
var value_dec = Blockly.Python.valueToCode(block, 'dec', Blockly.Python.ORDER_ATOMIC); var value_dec = Blockly.Python.valueToCode(block, 'dec', Blockly.Python.ORDER_ATOMIC);
var code = `'0x' + format(${value_dec}, 'X')`; var code = `f'{${value_dec}:#04x}'`;
return [code, Blockly.Python.ORDER_NONE]; return [code, Blockly.Python.ORDER_NONE];
}; };
/** GPIO *****************************************************************************************************/ /** GPIO *****************************************************************************************************/
@ -371,15 +278,15 @@ var ugjGpioSetInputDefinition = {
"options": [ "options": [
[ [
"%{BKY_GPIO_SET_INPUT_PULLUP}", "%{BKY_GPIO_SET_INPUT_PULLUP}",
"_pi.PULL_UP" "PULL_UP"
], ],
[ [
"%{BKY_GPIO_SET_INPUT_PULLDOWN}", "%{BKY_GPIO_SET_INPUT_PULLDOWN}",
"_pi.PULL_DOWN" "PULL_DOWN"
], ],
[ [
"%{BKY_GPIO_SET_INPUT_PULLNONE}", "%{BKY_GPIO_SET_INPUT_PULLNONE}",
"_pi.PULL_NONE" "PULL_NONE"
] ]
] ]
} }
@ -399,15 +306,18 @@ Blockly.Blocks['ugj_gpio_set_input'] = {
Blockly.JavaScript['ugj_gpio_set_input'] = function (block) { Blockly.JavaScript['ugj_gpio_set_input'] = function (block) {
var value_gpio = Blockly.JavaScript.valueToCode(block, 'gpio', Blockly.JavaScript.ORDER_ATOMIC); var value_gpio = Blockly.JavaScript.valueToCode(block, 'gpio', Blockly.JavaScript.ORDER_ATOMIC);
var dropdown_lflag = block.getFieldValue('lflag'); var dropdown_lflag = block.getFieldValue('lflag');
var code = `await _pi.gpio_set_input(${value_gpio}, ${dropdown_lflag});\n`; var code = `await _pi.gpio_set_input(${value_gpio}, _pi.${dropdown_lflag});\n`;
return code;
};
Blockly.Python['ugj_gpio_set_input'] = function (block) {
var value_gpio = Blockly.Python.valueToCode(block, 'gpio', Blockly.Python.ORDER_ATOMIC);
var dropdown_lflag = block.getFieldValue('lflag');
let lflag;
if (dropdown_lflag == 'PULL_NONE') { lflag = 'None'; }
else { lflag = `Pin.${dropdown_lflag}`; }
var code = `_pin[${value_gpio}] = Pin(${value_gpio}, Pin.IN, ${lflag})\n`;
return code; return code;
}; };
// Blockly.Python['ugj_gpio_set_input'] = function (block) {
// var value_gpio = Blockly.Python.valueToCode(block, 'gpio', Blockly.Python.ORDER_ATOMIC);
// var dropdown_lflag = block.getFieldValue('lflag');
// var code = `\n`;
// return code;
// };
/********************* */ /********************* */
/** Read GPIO Value ** */ /** Read GPIO Value ** */
@ -438,11 +348,11 @@ Blockly.JavaScript['ugj_gpio_read'] = function (block) {
var code = `await _pi.gpio_read(${value_gpio})`; var code = `await _pi.gpio_read(${value_gpio})`;
return [code, Blockly.JavaScript.ORDER_NONE]; return [code, Blockly.JavaScript.ORDER_NONE];
}; };
// Blockly.Python['ugj_gpio_read'] = function (block) { Blockly.Python['ugj_gpio_read'] = function (block) {
// var value_gpio = Blockly.Python.valueToCode(block, 'gpio', Blockly.Python.ORDER_ATOMIC); var value_gpio = Blockly.Python.valueToCode(block, 'gpio', Blockly.Python.ORDER_ATOMIC);
// var code = ``; var code = `_pin[${value_gpio}].value()`;
// return [code, Blockly.Python.ORDER_NONE]; return [code, Blockly.Python.ORDER_NONE];
// }; };
/*******************************************/ /*******************************************/
/** GPIO Write Value - Common GPIO on/off **/ /** GPIO Write Value - Common GPIO on/off **/
@ -775,14 +685,15 @@ Blockly.JavaScript['ugj_i2c_open'] = function (block) {
var code = `await _pi.i2c_open(${elutil.i2c_bus}, ${value_i2c_address});\n`; var code = `await _pi.i2c_open(${elutil.i2c_bus}, ${value_i2c_address});\n`;
return code; return code;
}; };
// Blockly.Python['ugj_i2c_open'] = function (block) { Blockly.Python['ugj_i2c_open'] = function (block) {
// var value_i2c_address = Blockly.Python.valueToCode(block, 'i2c_address', Blockly.Python.ORDER_ATOMIC); var value_i2c_address = Blockly.Python.valueToCode(block, 'i2c_address', Blockly.Python.ORDER_ATOMIC);
// Blockly.Python.provideFunction_( Blockly.Python.provideFunction_(
// 'import_lgpio', ['import lgpio as pi'] 'import_i2c', ['from machine import I2C']
// ); );
// var code = `i2c_hand = pi.i2c_open(1, ${value_i2c_address})\n`; var code = `_addr = ${value_i2c_address}
// return code; _i2c_hand = I2C(0,sda=Pin(0),scl=Pin(1))\n`;
// }; return code;
};
/********************** */ /********************** */
/** Close I2C Device ** */ /** Close I2C Device ** */
/********************** */ /********************** */
@ -805,10 +716,10 @@ Blockly.JavaScript['ugj_i2c_close'] = function (block) {
var code = `await _pi.i2c_close();\n`; var code = `await _pi.i2c_close();\n`;
return code; return code;
}; };
// Blockly.Python['ugj_i2c_close'] = function (block) { Blockly.Python['ugj_i2c_close'] = function (block) {
// var code = `await pi.i2c_close(i2c_hand)\n`; var code = ``;
// return code; return code;
// }; };
/****************************************************************** */ /****************************************************************** */
/** Writes a single byte to the specified register of the device ** */ /** Writes a single byte to the specified register of the device ** */
@ -846,12 +757,12 @@ Blockly.JavaScript['ugj_i2c_write_byte_data'] = function (block) {
var code = `await _pi.i2c_write_byte_data(${value_reg}, ${value_byte_val});\n`; var code = `await _pi.i2c_write_byte_data(${value_reg}, ${value_byte_val});\n`;
return code; return code;
}; };
// Blockly.Python['ugj_i2c_write_byte_data'] = function (block) { Blockly.Python['ugj_i2c_write_byte_data'] = function (block) {
// var value_reg = Blockly.Python.valueToCode(block, 'reg', Blockly.Python.ORDER_ATOMIC); var value_reg = Blockly.Python.valueToCode(block, 'reg', Blockly.Python.ORDER_ATOMIC);
// var value_byte_val = Blockly.Python.valueToCode(block, 'byte_val', Blockly.Python.ORDER_ATOMIC); var value_byte_val = Blockly.Python.valueToCode(block, 'byte_val', Blockly.Python.ORDER_ATOMIC);
// var code = `await pi.i2c_write_byte_data(i2c_hand, ${value_reg}, ${value_byte_val})\n`; var code = `_i2c_hand.writeto_mem(_addr, ${value_reg}, (${value_byte_val}).to_bytes(1,'big'))\n`;
// return code; return code;
// }; };
/****************************************************************** */ /****************************************************************** */
/** Read a single byte from the specified resister of the device ** */ /** Read a single byte from the specified resister of the device ** */
@ -882,11 +793,11 @@ Blockly.JavaScript['ugj_i2c_read_byte_data'] = function (block) {
var code = `await _pi.i2c_read_byte_data(${value_reg})`; var code = `await _pi.i2c_read_byte_data(${value_reg})`;
return [code, Blockly.JavaScript.ORDER_ATOMIC]; return [code, Blockly.JavaScript.ORDER_ATOMIC];
}; };
// Blockly.Python['ugj_i2c_read_byte_data'] = function (block) { Blockly.Python['ugj_i2c_read_byte_data'] = function (block) {
// var value_reg = Blockly.Python.valueToCode(block, 'reg', Blockly.Python.ORDER_ATOMIC); var value_reg = Blockly.Python.valueToCode(block, 'reg', Blockly.Python.ORDER_ATOMIC);
// var code = `await pi.i2c_read_byte_data(i2c_hand, ${value_reg})\n`; var code = `int.from_bytes(_i2c_hand.readfrom_mem(_addr, ${value_reg}, 1), 'big')\n`;
// return [code, Blockly.Python.ORDER_ATOMIC]; return [code, Blockly.Python.ORDER_ATOMIC];
// }; };
Blockly.Blocks['ugj_i2c_read_word_data'] = { Blockly.Blocks['ugj_i2c_read_word_data'] = {
init: function () { init: function () {
@ -941,13 +852,12 @@ Blockly.JavaScript['ugj_i2c_write_i2c_block_data'] = function (block) {
var code = `await _pi.i2c_write_i2c_block_data (${value_reg}, ${value_data});`; var code = `await _pi.i2c_write_i2c_block_data (${value_reg}, ${value_data});`;
return code; return code;
}; };
// Blockly.Python['ugj_i2c_write_i2c_block_data'] = function (block) { Blockly.Python['ugj_i2c_write_i2c_block_data'] = function (block) {
// var value_reg = Blockly.Python.valueToCode(block, 'reg', Blockly.Python.ORDER_ATOMIC); var value_reg = Blockly.Python.valueToCode(block, 'reg', Blockly.Python.ORDER_ATOMIC);
// var value_name = Blockly.Python.valueToCode(block, 'NAME', Blockly.Python.ORDER_ATOMIC); var value_data = Blockly.Python.valueToCode(block, 'data', Blockly.Python.ORDER_ATOMIC);
// // TODO: Assemble Python into code variable. var code = `_i2c_hand.writeto_mem(_addr, ${value_reg}, bytearray(${value_data}))\n`;
// var code = '...\n'; return code;
// return code; };
// };
/************************************************************************** */ /************************************************************************** */
/** Returns count bytes read from the raw device associated with handle. ** */ /** Returns count bytes read from the raw device associated with handle. ** */
@ -2833,6 +2743,118 @@ Blockly.JavaScript['testblock'] = function (block) {
/** 互換性 */ /** 互換性 */
/** Fix Basic Blocks ****************************************************************************************/
Blockly.Blocks['ugj_control_for'] = {
init: function () {
this.appendValueInput("index")
.setCheck("Variable");
this.appendValueInput("from")
.setCheck("Number")
.appendField("を");
this.appendValueInput("to")
.setCheck("Number")
.appendField("から");
this.appendValueInput("by")
.setCheck("Number")
.appendField("まで");
this.appendDummyInput()
.appendField("ずつ")
.appendField(new Blockly.FieldDropdown([["増やして", "+"], ["減らして", "-"]]), "crease");
this.appendStatementInput("do")
.setCheck(null);
this.setInputsInline(true);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setTooltip("インデックス番号を決められた数ずつ増やし(減らし)ながら、ステートメントを実行します。");
this.setHelpUrl("");
this.setStyle('loop_blocks');
}
};
Blockly.JavaScript['ugj_control_for'] = function (block) {
var value_index = Blockly.JavaScript.valueToCode(block, 'index', Blockly.JavaScript.ORDER_ATOMIC);
// var variable_index = Blockly.JavaScript.nameDB_.getName(block.getFieldValue('index'), Blockly.Variables.NAME_TYPE);
var value_from = Blockly.JavaScript.valueToCode(block, 'from', Blockly.JavaScript.ORDER_ATOMIC);
var value_to = Blockly.JavaScript.valueToCode(block, 'to', Blockly.JavaScript.ORDER_ATOMIC);
var value_by = Blockly.JavaScript.valueToCode(block, 'by', Blockly.JavaScript.ORDER_ATOMIC);
var dropdown_crease = block.getFieldValue('crease');
var statements_do = Blockly.JavaScript.statementToCode(block, 'do');
let daishou;
if (dropdown_crease == '+') { daishou = '<'; }
else { daishou = '>'; }
var code = [
`for (${value_index} = ${value_from}; ${value_index} ${daishou}= ${value_to}; ${value_index} ${dropdown_crease}= ${Math.abs(value_by)}) {`,
statements_do,
`}`,
''
].join('\n');
return code;
};
Blockly.Python['ugj_control_for'] = function (block) {
var value_index = Blockly.Python.valueToCode(block, 'index', Blockly.Python.ORDER_ATOMIC);
// var variable_index = Blockly.Python.nameDB_.getName(block.getFieldValue('index'), Blockly.Variables.NAME_TYPE);
var value_from = Blockly.Python.valueToCode(block, 'from', Blockly.Python.ORDER_ATOMIC);
var value_to = Blockly.Python.valueToCode(block, 'to', Blockly.Python.ORDER_ATOMIC);
var value_by = Blockly.Python.valueToCode(block, 'by', Blockly.Python.ORDER_ATOMIC);
var dropdown_crease = block.getFieldValue('crease');
var statements_do = Blockly.Python.statementToCode(block, 'do');
if (statements_do === '') statements_do = ' pass';
if (dropdown_crease == '+') { value_by = Math.abs(value_by); value_to++; }
else { value_by = Math.abs(value_by) * (-1); value_to--; }
var code = [
`for ${value_index} in range(${value_from}, ${value_to}, ${value_by}) :`,
statements_do,
''
].join('\n');
return code;
};
Blockly.Blocks['ugj_controls_foreach'] = {
init: function () {
this.appendValueInput("list")
.setCheck("Array")
.appendField("リスト");
this.appendValueInput("item")
.setCheck("Variable")
.appendField("の各");
this.appendDummyInput()
.appendField("について");
this.appendStatementInput("do")
.setCheck(null);
this.setInputsInline(true);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setTooltip("リストの各項目について、その項目の内容を変数「項目」に代入してステートメントを実行します。");
this.setHelpUrl("");
this.setStyle('loop_blocks');
}
};
Blockly.JavaScript['ugj_controls_foreach'] = function (block) {
var value_list = Blockly.JavaScript.valueToCode(block, 'list', Blockly.JavaScript.ORDER_ATOMIC);
var value_item = Blockly.JavaScript.valueToCode(block, 'item', Blockly.JavaScript.ORDER_ATOMIC);
var statements_do = Blockly.JavaScript.statementToCode(block, 'do');
var code = [
`for (let _index in ${value_list}) {`,
`${value_item} = ${value_list}[_index];`,
statements_do,
`}`,
''
].join('\n');
return code;
};
Blockly.Python['ugj_controls_foreach'] = function (block) {
var value_list = Blockly.Python.valueToCode(block, 'list', Blockly.Python.ORDER_ATOMIC);
var value_item = Blockly.Python.valueToCode(block, 'item', Blockly.Python.ORDER_ATOMIC);
var statements_do = Blockly.Python.statementToCode(block, 'do');
if (statements_do === '') statements_do = ' pass';
var code = [
`for ${value_item} in ${value_list}:`,
statements_do,
''
].join('\n');
return code;
};
// /******************/ // /******************/
// /** Set Interval **/ // /** Set Interval **/
// /******************/ // /******************/