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

View File

@ -76,6 +76,10 @@ var theme = Blockly.Theme.defineTheme('ocoge', {
// Customize messages
Blockly.Msg["CONTROLS_IF_MSG_THEN"] = "ならば";
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["VARIABLES_SET"] = "変数 %1 を %2 にする";
// 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 をコール
const ugj_pyBeautify = (code) => {
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();
if (!formatted) formatted = code;
return formatted;
@ -349,7 +340,6 @@ const ugj_createCode = (args) => {
window.alert('Python 非対応のブロックが使用されています。\n' + e.message);
code = '';
}
// code = Blockly.Python.workspaceToCode(workspace);
}
else { // Javascript コード出力
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 () => {
if (elutil.lang == 'js') {
document.activeElement.blur(); //実行ボタンからフォーカスを外す:エンターキー押下が悪さをするため
@ -445,8 +397,8 @@ const ugj_spawnPyboard = (code, mode) => {
p.stderr.on('data', d => { console.error(d.toString()) });
p.stdout.on('data', d => { console.log(d.toString()) });
p.on('close', c => {
if (c == 0) console.log(`正常終了`);
else window.alert(`エラーが発生しました。詳しくはコンソールを参照してください。`);
if (c == 0) console.log(`コード実行 OK`);
else _fukidashi(`実行時エラーが発生しました。詳しくはコンソールを参照してください。`, 5);
});
}
@ -454,13 +406,11 @@ const ugj_spawnPyboard = (code, mode) => {
// エレメントのオブジェクトとかコールバックとか Python対応とか
// 色々この中で完結させてみる
const ugj_showCode = () => {
// var ext = 'js';
var ext = elutil.lang;
const dialog = document.getElementById('codeDlg');
const content = document.getElementById('dlgContent');
const btn_close = document.getElementById('dlgClose');
const btn_export = document.getElementById('dlgExport');
// const chkbox_cli = document.getElementById('dlgCli');
const dialog_title = document.getElementById('dlgTitle');
@ -484,7 +434,6 @@ const ugj_showCode = () => {
const export_cb = () => {
if (ext == 'js') {
let code = ugj_createCode({ 'ext': ext, 'async': true, 'beautify': true });
// if (elutil.saveFile(code, ext) === false) window.alert('保存できませんでした。');
save_to_file(code);
} else {
let code = ugj_createCode({ 'ext': 'py', 'beautify': true });
@ -493,23 +442,18 @@ const ugj_showCode = () => {
close_cb();
}
const keyev_cb = ev => {
if (ev.key == 'c' && ext == 'js') {
// CLI モード
// blackboardWrite()とwindow.alert()、fukidashi()をconsole.log()に書き換え、
// document... と ugj_... と elutil... をコメントアウト(ブラウザ関連部分の追放という意味では不完全なので注意)
// あと正規表現もいい加減
if (ev.key == 's' && ev.ctrlKey) {
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 (elutil.saveFile(code, ext) === false) window.alert('保存できませんでした。');
save_to_file(code);
close_cb();
} else if (ev.key == 'f' && ext == 'py') {
let code = ugj_createCode({ 'ext': ext, 'beautify': true });
// if (elutil.saveFile(code, ext) === false) window.alert('保存できませんでした。');
if (ext == 'js') {
// JS-CLI モード
// blackboardWrite()とwindow.alert()、fukidashi()をconsole.log()に書き換え、
// document... と ugj_... と elutil... をコメントアウト(ブラウザ関連部分の追放という意味では不完全なので注意)
// あと正規表現もいい加減
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 */');
}
save_to_file(code);
close_cb();
}
}
btn_close.addEventListener('click', close_cb);
btn_export.addEventListener('click', export_cb);

View File

@ -229,7 +229,7 @@ class elUtil {
filter = { name: 'text file', extensions: ['txt'] };
}
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;
}
// ファイル書き込み

View File

@ -7,7 +7,16 @@ import os
import sys
import pyboard
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
@ -16,118 +25,168 @@ gport = None
# リストボックスにドロップ
def listbox_drop(event):
files = listbox.tk.splitlist(event.data)
for f in 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)
putfiles(files)
# キーボード
def input_key(ev):
# print(ev)
if ev.keysym == 'F5':
filelist()
reload()
elif ev.keysym == 'Delete':
selected = listbox.curselection()
for i in selected:
src = listbox.get(i)
call_pybfunc('fs_rm', src)
print('Deleted %s' % src)
if len(selected):
filelist()
def on_closing(errmsg=''):
if errmsg:
messagebox.showerror('Error', errmsg)
root.destroy()
sys.exit(0)
rmfiles()
# ダブルクリック
def dbl_click(ev):
run()
# 右クリックメニュー
def pop_menu(ev):
listbox.select_clear(0, END)
listbox.select_set(listbox.nearest(ev.y))
pmenu.post(ev.x_root, ev.y_root)
##### pyboard関数 #####
# 接続・repl開始
def connect():
global gport
try:
pyb = pyboard.Pyboard(gport)
pyb.enter_raw_repl()
return pyb
except:
on_closing('デバイスに接続できません')
except pyboard.PyboardError as err:
gport = None
listbox.delete(0, END)
set_title('Lost device : Please reload')
raise pyboard.PyboardError('Lost device')
pyb.enter_raw_repl(False)
return pyb
# repl終了・切断
def disconnect(pyb):
try:
pyb.exit_raw_repl()
pyb.close()
except:
on_closing('切断に失敗しました')
# コマンド実行
def exec_command(cmd):
pyb = connect()
except Exception as err:
pass
try:
retval = pyb.exec_(cmd)
except:
on_closing('コマンド実行時にエラーが発生しました')
disconnect(pyb)
return retval.decode('utf-8')
# pyboard.py の関数をコール
def call_pybfunc(funcname, *args):
pyb.close()
except Exception as err:
pass
# ファイル送信 (複数可)(files: list of local filepath)
def putfiles(files):
pyb = connect()
if funcname=='fs_put':
pyb.fs_put(args[0], args[1])
elif funcname=='fs_rm':
pyb.fs_rm(args[0])
for src in files:
if os.path.exists(src):
if os.path.isfile(src):
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)
def initialize():
# ポートスキャン:アルファベット順で一番若いポートを返す
def find_device():
global gport
for p in sorted(serial.tools.list_ports.comports()):
if p.hwid.startswith('USB'):
gport = p.device
set_title(gport)
filelist()
break
else:
on_closing('デバイスがみつかりません')
def list_clear():
listbox.delete(0, END)
def filelist():
list_clear()
files = ls()
for f in files:
listbox.insert(END, f)
def ls(src='/'):
gport = None
set_title('No device')
raise OSError('Device not found')
# 再読込:ここのみデバイスの再スキャンが入る
def reload():
if not gport:
find_device()
if gport:
listfiles()
# ファイルリスト取得だけを行う
def listfiles():
pyb = connect()
ls(pyb)
disconnect(pyb)
# ファイルリストを取得し、リストボックスに表示 (pyb: pyboard handle, src: target directory on device)
def ls(pyb, src='/'):
cmd = (
"import uos\nfor f in uos.listdir(%s):\n"
" print(f)"
% (("'%s'" % src) if src else "")
)
retval = exec_command(cmd)
return retval.splitlines()
def putfile(src):
dest = os.path.basename(src)
call_pybfunc('fs_put', src, dest)
retval = pyb.exec(cmd)
files = retval.decode('utf-8').splitlines()
listbox.delete(0, END)
for f in files:
listbox.insert(END, f)
# ウィンドウタイトル (title: string)
def set_title(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.protocol("WM_DELETE_WINDOW", on_closing)
root.title('PyBfm')
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')
# Frameウィジェットの生成
frame = Frame(root)
@ -136,6 +195,8 @@ listbox = Listbox(frame, selectmode=EXTENDED)
listbox.drop_target_register(DND_FILES)
listbox.dnd_bind('<<Drop>>', listbox_drop)
listbox.bind("<KeyPress>", input_key)
listbox.bind("<Double-Button-1>", dbl_click)
listbox.bind("<Button-3>", pop_menu)
# スクロールバーの生成
scroll = Scrollbar(frame, orient=VERTICAL)
listbox.configure(yscrollcommand=scroll.set)
@ -145,6 +206,11 @@ frame.pack(expand=True,fill=BOTH)
listbox.pack(expand=True,fill=BOTH, side=LEFT)
scroll.pack(side=RIGHT, fill=Y)
initialize()
try:
find_device()
except Exception as err:
pass
else:
listfiles()
root.mainloop()

View File

@ -26,7 +26,7 @@ pyb.enter_raw_repl()
if mode == 'r':
print('Run code', flush=True)
pyb.exec(src)
pyb.exec_raw_no_follow(src)
elif mode == 'd':
print('Deploy code', flush=True)
pyb.exec("f=open('%s','wb')\nw=f.write" % dest)
@ -43,3 +43,4 @@ elif mode == 'd':
pyb.exec("f.close()")
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",
"version": "0.1.7",
"version": "0.1.8",
"description": "ブロックベースビジュアルプログラム開発・実行環境",
"main": "main.js",
"scripts": {
@ -22,9 +22,9 @@
},
"homepage": "https://git.ocoge.club/ocoge.club/ocoge#readme",
"devDependencies": {
"@electron-forge/cli": "^6.0.0-beta.64",
"@electron-forge/maker-deb": "^6.0.0-beta.64",
"electron": "^19.0.8",
"@electron-forge/cli": "^6.0.0-beta.65",
"@electron-forge/maker-deb": "^6.0.0-beta.65",
"electron": "^19.0.9",
"electron-rebuild": "^3.2.8"
},
"dependencies": {
@ -32,8 +32,8 @@
"@tensorflow-models/blazeface": "^0.0.7",
"@tensorflow-models/knn-classifier": "^1.2.4",
"@tensorflow-models/mobilenet": "^2.1.0",
"@tensorflow/tfjs": "^3.18.0",
"@tensorflow/tfjs-backend-wasm": "^3.18.0",
"@tensorflow/tfjs": "^3.19.0",
"@tensorflow/tfjs-backend-wasm": "^3.19.0",
"axios": "^0.27.2",
"node-abi": "^3.22.0",
"nodemailer": "^6.7.7",
@ -58,4 +58,4 @@
]
}
}
}
}

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
Blockly.FieldColour.COLOURS = [
'#ffffff', '#808000', '#ffff00', '#ff00ff', '#ff4500',
@ -193,6 +95,11 @@ Blockly.JavaScript['ugj_bintodec'] = function (block) {
var code = `parseInt (${value_bin}, 2)`;
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 = {
"type": "ugj_hextodec",
@ -254,7 +161,7 @@ Blockly.JavaScript['ugj_dectohex'] = function (block) {
};
Blockly.Python['ugj_dectohex'] = function (block) {
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];
};
/** GPIO *****************************************************************************************************/
@ -371,15 +278,15 @@ var ugjGpioSetInputDefinition = {
"options": [
[
"%{BKY_GPIO_SET_INPUT_PULLUP}",
"_pi.PULL_UP"
"PULL_UP"
],
[
"%{BKY_GPIO_SET_INPUT_PULLDOWN}",
"_pi.PULL_DOWN"
"PULL_DOWN"
],
[
"%{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) {
var value_gpio = Blockly.JavaScript.valueToCode(block, 'gpio', Blockly.JavaScript.ORDER_ATOMIC);
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;
};
// 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 ** */
@ -438,11 +348,11 @@ Blockly.JavaScript['ugj_gpio_read'] = function (block) {
var code = `await _pi.gpio_read(${value_gpio})`;
return [code, Blockly.JavaScript.ORDER_NONE];
};
// Blockly.Python['ugj_gpio_read'] = function (block) {
// var value_gpio = Blockly.Python.valueToCode(block, 'gpio', Blockly.Python.ORDER_ATOMIC);
// var code = ``;
// return [code, Blockly.Python.ORDER_NONE];
// };
Blockly.Python['ugj_gpio_read'] = function (block) {
var value_gpio = Blockly.Python.valueToCode(block, 'gpio', Blockly.Python.ORDER_ATOMIC);
var code = `_pin[${value_gpio}].value()`;
return [code, Blockly.Python.ORDER_NONE];
};
/*******************************************/
/** 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`;
return code;
};
// Blockly.Python['ugj_i2c_open'] = function (block) {
// var value_i2c_address = Blockly.Python.valueToCode(block, 'i2c_address', Blockly.Python.ORDER_ATOMIC);
// Blockly.Python.provideFunction_(
// 'import_lgpio', ['import lgpio as pi']
// );
// var code = `i2c_hand = pi.i2c_open(1, ${value_i2c_address})\n`;
// return code;
// };
Blockly.Python['ugj_i2c_open'] = function (block) {
var value_i2c_address = Blockly.Python.valueToCode(block, 'i2c_address', Blockly.Python.ORDER_ATOMIC);
Blockly.Python.provideFunction_(
'import_i2c', ['from machine import I2C']
);
var code = `_addr = ${value_i2c_address}
_i2c_hand = I2C(0,sda=Pin(0),scl=Pin(1))\n`;
return code;
};
/********************** */
/** Close I2C Device ** */
/********************** */
@ -805,10 +716,10 @@ Blockly.JavaScript['ugj_i2c_close'] = function (block) {
var code = `await _pi.i2c_close();\n`;
return code;
};
// Blockly.Python['ugj_i2c_close'] = function (block) {
// var code = `await pi.i2c_close(i2c_hand)\n`;
// return code;
// };
Blockly.Python['ugj_i2c_close'] = function (block) {
var code = ``;
return code;
};
/****************************************************************** */
/** 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`;
return code;
};
// Blockly.Python['ugj_i2c_write_byte_data'] = function (block) {
// 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 code = `await pi.i2c_write_byte_data(i2c_hand, ${value_reg}, ${value_byte_val})\n`;
// return code;
// };
Blockly.Python['ugj_i2c_write_byte_data'] = function (block) {
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 code = `_i2c_hand.writeto_mem(_addr, ${value_reg}, (${value_byte_val}).to_bytes(1,'big'))\n`;
return code;
};
/****************************************************************** */
/** 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})`;
return [code, Blockly.JavaScript.ORDER_ATOMIC];
};
// Blockly.Python['ugj_i2c_read_byte_data'] = function (block) {
// 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`;
// return [code, Blockly.Python.ORDER_ATOMIC];
// };
Blockly.Python['ugj_i2c_read_byte_data'] = function (block) {
var value_reg = Blockly.Python.valueToCode(block, 'reg', Blockly.Python.ORDER_ATOMIC);
var code = `int.from_bytes(_i2c_hand.readfrom_mem(_addr, ${value_reg}, 1), 'big')\n`;
return [code, Blockly.Python.ORDER_ATOMIC];
};
Blockly.Blocks['ugj_i2c_read_word_data'] = {
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});`;
return code;
};
// Blockly.Python['ugj_i2c_write_i2c_block_data'] = function (block) {
// var value_reg = Blockly.Python.valueToCode(block, 'reg', Blockly.Python.ORDER_ATOMIC);
// var value_name = Blockly.Python.valueToCode(block, 'NAME', Blockly.Python.ORDER_ATOMIC);
// // TODO: Assemble Python into code variable.
// var code = '...\n';
// return code;
// };
Blockly.Python['ugj_i2c_write_i2c_block_data'] = function (block) {
var value_reg = Blockly.Python.valueToCode(block, 'reg', Blockly.Python.ORDER_ATOMIC);
var value_data = Blockly.Python.valueToCode(block, 'data', Blockly.Python.ORDER_ATOMIC);
var code = `_i2c_hand.writeto_mem(_addr, ${value_reg}, bytearray(${value_data}))\n`;
return code;
};
/************************************************************************** */
/** 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 **/
// /******************/