従来 ver. 0.7.0
課題
ver. 0.7.0 では、次の課題があるので、改善したい。
-
machine/state
状態を管理する変数が2つある(machine, state) -
説明の記述方法
状態名称(遷移を含む)と説明とが1つの引数で記述されている -
複数の遷移先(説明記述)
遷移先が複数ある場合を想定し、その遷移先を配列で指定できるが、説明の記述も複数必要である -
イベント依存
micro:bitのイベントに依存している -
ポーリング間隔
時間待ちループで、タイムアウトをポーリングしている
ソースコード(ブロック定義)
num StateMachines {
M0 = 0,
M1,
M2,
M3,
M4,
M5
}
/**
* mstate blocks
* Defining blocks: https://makecode.com/defining-blocks
* Playground: https://makecode.com/playground
* icon: a Unicode identifier for an icon from the Font Awesome icon set.
* http://fontawesome.io/icons
*/
//% weight=100 color="#4C97FF" icon="\uf362"
//% groups="['Command', 'Declare', 'Transit']"
namespace mstate {
/**
* convert state/trigger name (string) to id (number): new id if undefined
* @param name state name (string) or trigger name (string)
* @returns state id or trigger id
*/
//% block="id of $name"
//% name.defl="a"
//% weight=210
//% advanced=true
export function convId(name: string): number {
}
/**
* Internal event settings
* @param aStateMachine StateMachines
* @param eventId Event ID (default: 32868 = 32768 + 100)
* @param ms Event loop interval (default: 100ms)
*/
//% block="settings [$aStateMachine] event ID: $eventId every: $ms ms"
//% aStateMachine.defl=StateMachines.M0
//% eventId.defl=32768
//% ms.shadow="timePicker"
//% ms.defl=100
//% weight=190
//% advanced=true
export function settingsMachineEvent(aStateMachine: StateMachines, eventId: number,
ms: number
) {
}
/**
* define state
* @param aStateMachine StateMachines
* @param aStateName state name
* @param body code to run, (machine: machine ID, state: state ID)
*/
//% block="define [$machine,$state] to $aStateMachine $aStateName"
//% aStateMachine.defl=StateMachines.M0
//% aStateName.defl="a"
//% draggableParameters="reporter"
//% weight=180
//% group="Declare"
export function defineState(aStateMachine: StateMachines, aStateName: string,
body: (machine: number, state: number) => void
) {
}
/**
* declare ENTRY action.
* @param aMachine machine ID
* @param aState state ID
* @param body code to run
*/
//% block="on entry [$aMachine,$aState]"
//% aMachine.defl=0
//% aState.defl=0
//% handlerStatement
//% weight=170
//% group="Declare"
export function declareEntry(aMachine: number, aState: number,
body: () => void
) {
}
/**
* declare DO activity.
* @param aMachine machine ID
* @param aState state ID
* @param aEvery interval time (milliseconds)
* @param body code to run
*/
//% block="on do [$aMachine,$aState] every $aEvery ms"
//% aMachine.defl=0
//% aState.defl=0
//% aEvery.shadow="timePicker"
//% handlerStatement
//% weight=160
//% group="Declare"
export function declareDo(aMachine: number, aState: number, aEvery: number,
body: () => void
) {
}
/**
* declare EXIT action.
* @param aMachine machine ID
* @param aState state ID
* @param body code to run
*/
//% block="on exit [$aMachine,$aState]"
//% aMachine.defl=0
//% aState.defl=0
//% handlerStatement
//% weight=150
//% group="Declare"
export function declareExit(aMachine: number, aState: number,
body: () => void
) {
}
/**
* declare simple transition.
* @param aMachine machine ID
* @param aState state ID
* @param aTriggerName trigger name
* @param aToName next state nam
*/
//% block="trasition [$aMachine,$aState] when $aTriggerName to $aToName"
//% aMachine.defl=0
//% aState.defl=0
//% aTriggerName.defl="e"
//% aToName.defl="a"
//% inlineInputMode=inline
//% weight=140
//% group="Transition"
export function declareSimpleTransition(aMachine: number, aState: number,
aTriggerName: string, aToName: string
) {
}
/**
* declare timeouted transition.
* @param aMachine machine ID
* @param aState state ID
* @param aMs timeout (ms)
* @param aToName next state name
*/
//% block="trasition [$aMachine,$aState] timeouted $aMs to $aToName"
//% aMachine.defl=0
//% aState.defl=0
//% aMs.shadow="timePicker"
//% aToName.defl="a"
//% inlineInputMode=inline
//% weight=130
//% group="Transition"
export function declareTimeoutedTransition(aMachine: number, aState: number,
aMs: number, aToName: string
) {
}
/**
* declare custom transition.
* @param aMachine machine ID
* @param aState state ID
* @param aTriggerName trigger name
* @param aTransList array of next state name
* @param body code to run
*/
//% block="trasition [$aMachine,$aState] when $aTriggerName $args to $aTransList"
//% aMachine.defl=0
//% aState.defl=0
//% aTriggerName.defl="e"
//% draggableParameters="reporter"
//% handlerStatement
//% weight=120
//% group="Transition"
export function declareCustomTransition(aMachine: number, aState: number,
aTriggerName: string, aTransList: string[],
body: () => void
) {
}
/**
* is timeouted.
* @param aMachine machine ID
* @param aMs timeout (milliseconds)
*/
//% block="timeouted [$aMachine] $aMs"
//% aMachine.defl=0
//% aMs.shadow="timePicker"
//% weight=110
//% group="Transition"
export function isTimeouted(aMachine: number, aMs: number): boolean {
}
/**
* trigger args.
* @param aMachine machine ID
* @returns trigger args
*/
//% block="trigger args [$aMachine]"
//% aMachine.defl=0
//% weight=105
//% group="Transition"
//% advanced=true
export function getTriggerArgs(aMachine: number): number[] {
}
/**
* transit to.
* @param aMachine machine ID
* @param index states index]
*/
//% block="transit [$aMachine] at $index"
//% aMachine.defl=0
//% index.defl=0
//% weight=100
//% group="Transition"
export function transitTo(aMachine: number, index: number) {
}
/**
* send trigger
* @param aStateMachine StateMachines
* @param aTriggerName trigger name
*/
//% block="send $aStateMachine $aTriggerName"
//% aStateMachine.defl=StateMachines.M0
//% aTriggerName.defl="e"
//% weight=95
//% group="Command"
export function send(aStateMachine: StateMachines, aTriggerName: string) {
}
/**
* send trigger with args
* @param aStateMachine StateMachines
* @param aTriggerName trigger name
* @param aTriggerArgs args
*/
//% block="send $aStateMachine $aTriggerName $aTriggerArgs"
//% aStateMachine.defl=StateMachines.M0
//% aTriggerName.defl="e"
//% weight=90
//% group="Command"
//% advanced=true
export function sendWith(aStateMachine: StateMachines, aTriggerName: string,
aTriggerArgs: number[]
) {
}
/**
* start state machine
* @param aStateMachine StateMachines
* @param aStateName default state name
*/
//% block="start $aStateMachine $aStateName"
//% aStateMachine.defl=StateMachines.M0
//% aStateName.defl="a"
//% weight=80
//% group="Command"
export function start(aStateMachine: StateMachines, aStateName: string) {
}
/**
* export UML, PlantUML
* PlantUML Web server: http://www.plantuml.com/plantuml/
* @param aStateMachine
* @param aStateName default state
*/
//% block="UML $aStateMachine $aStateName"
//% aStateMachine.defl=StateMachines.M0
//% aStateName.defl="a"
//% weight=70
//% group="Command"
//% shim=mstate::simu_export_uml
//% advanced=true
export function exportUml(aStateMachine: StateMachines, aStateName: string) {
}
/**
* UML state
* @param aMachine machine ID
* @param aStateName state name
*/
//% block
//% shim=mstate::simu_state_uml
//% blockHidden=true
//% advanced=true
export function _simuStateUml(aMachine: number, aStateName: string) {
}
/**
* UML transition
* @param aMachine machine ID
* @param aState state ID
* @param aTransList array of next state name
*/
//% block
//% shim=mstate::simu_transition_uml
//% blockHidden=true
//% advanced=true
export function _simuTransitionUml(aMachine: number, aState: number,
aTransList: string[]
) {
}
/**
* convert id (number) to state/trigger name (string)
* @param id state id or trigger id
* @returns state name (string) or trigger name (string): "[<id>]" if undefined
*/
//% block
//% shim=mstate::simu_conv_name
//% blockHidden=true
//% advanced=true
export function _simuConvName(id: number): string {
}
}
対策 ver. 0.8.0
ブロック定義を試す
次のツールで、MakeCodeのブロック定義を試すことができます。
MakeCode Bolocks Playground - https://makecode.com/playground
課題1. machine/state
従来は、状態を管理する変数や引数が2つあった( machine
と state
)。
それを、1つにした( mstateId
)。
従来版 | 対策版 |
---|---|
ソースコード(ブロック定義)
enum StateMachines {
M0 = 0,
M1,
M2,
M3,
M4,
M5
}
/**
* mstate blocks
* Defining blocks: https://makecode.com/defining-blocks
* Playground: https://makecode.com/playground
* icon: a Unicode identifier for an icon from the Font Awesome icon set.
* http://fontawesome.io/icons
*/
//% weight=100 color="#4C97FF" icon="\uf362"
//% groups="['Command', 'Declare', 'Transit']"
namespace mstate {
/**
* convert state/trigger name (string) to id (number): new id if undefined
* @param aStateMachine StateMachines
* @param name state name (string) or trigger name (string)
* @returns machine-state id or machine-trigger id
*/
//% block="id of $aStateMachine $name"
//% aStateMachine.defl=StateMachines.M0
//% name.defl="a"
//% weight=210
//% advanced=true
export function convId(aStateMachine: StateMachines, name: string): number {
}
/**
* Internal event settings
* @param aStateMachine StateMachines
* @param eventId Event ID (default: 32868 = 32768 + 100)
* @param ms Event loop interval (default: 100ms)
*/
//% block="settings $aStateMachine event ID: $eventId every: $ms ms"
//% aStateMachine.defl=StateMachines.M0
//% eventId.defl=32768
//% ms.shadow="timePicker"
//% ms.defl=100
//% weight=190
//% advanced=true
export function settingsMachineEvent(aStateMachine: StateMachines, eventId: number,
ms: number
) {
}
/**
* define state
* @param aStateMachine StateMachines
* @param aStateName state name
* @param body code to run, (mstateId: machine-state ID)
*/
//% block="define $aStateMachine $mstateId to $aStateName"
//% aStateMachine.defl=StateMachines.M0
//% aStateName.defl="a"
//% draggableParameters="reporter"
//% weight=180
//% group="Declare"
export function defineState(aStateMachine: StateMachines, aStateName: string,
body: (mstateId: number) => void
) {
}
/**
* declare ENTRY action.
* @param machine-state ID
* @param body code to run
*/
//% block="mstate $aMstateId on entry"
//% $aMstateId.defl=0
//% handlerStatement
//% weight=170
//% group="Declare"
export function declareEntry(aMstateId: number,
body: () => void
) {
}
/**
* declare DO activity.
* @param machine-state ID
* @param aEvery interval time (milliseconds)
* @param body code to run
*/
//% block="mstate $aMstateId on do every $aEvery ms"
//% aMstateId.defl=0
//% aEvery.shadow="timePicker"
//% handlerStatement
//% weight=160
//% group="Declare"
export function declareDo(aMstateId: number, aEvery: number,
body: () => void
) {
}
/**
* declare EXIT action.
* @param machine-state ID
* @param body code to run
*/
//% block="mstate $aMstateId on exit"
//% aMstateId.defl=0
//% handlerStatement
//% weight=150
//% group="Declare"
export function declareExit(aMstateId: number,
body: () => void
) {
}
/**
* declare simple transition.
* @param machine-state ID
* @param aTriggerName trigger name
* @param aToName next state nam
*/
//% block="mstate $aMstateId trasition when $aTriggerName to $aToName"
//% aMstateId.defl=0
//% aTriggerName.defl="e"
//% aToName.defl="a"
//% inlineInputMode=inline
//% weight=140
//% group="Transition"
export function declareSimpleTransition(aMstateId: number,
aTriggerName: string, aToName: string
) {
}
/**
* declare timeouted transition.
* @param machine-state ID
* @param aMs timeout (ms)
* @param aToName next state name
*/
//% block="mstate $aMstateId trasition timeouted $aMs to $aToName"
//% aMstateId.defl=0
//% aMs.shadow="timePicker"
//% aToName.defl="a"
//% inlineInputMode=inline
//% weight=130
//% group="Transition"
export function declareTimeoutedTransition(aMstateId: number,
aMs: number, aToName: string
) {
}
/**
* declare custom transition.
* @param machine-state ID
* @param aTriggerName trigger name
* @param aTransList array of next state name
* @param body code to run
*/
//% block="mstate $aMstateId trasition when $aTriggerName $args to $aTransList"
//% aMstateId.defl=0
//% aTriggerName.defl="e"
//% draggableParameters="reporter"
//% handlerStatement
//% weight=120
//% group="Transition"
export function declareCustomTransition(aMstateId: number,
aTriggerName: string, aTransList: string[],
body: () => void
) {
}
/**
* is timeouted.
* @param machine-state ID, as machine ID
* @param aMs timeout (milliseconds)
*/
//% block="mstate $aMstateId timeouted $aMs"
//% aMstateId.defl=0
//% aMs.shadow="timePicker"
//% weight=110
//% group="Transition"
export function isTimeouted(aMstateId: number, aMs: number): boolean {
}
/**
* trigger args.
* @param machine-state ID, as machine ID
* @returns trigger args
*/
//% block="mstate $aMstateId trigger args"
//% aMstateId.defl=0
//% weight=105
//% group="Transition"
//% advanced=true
export function getTriggerArgs(aMstateId: number): number[] {
}
/**
* transit to.
* @param machine-state ID, as machine ID
* @param index states index]
*/
//% block="mstate $aMstateId transit at $index"
//% aMstateId.defl=0
//% index.defl=0
//% weight=100
//% group="Transition"
export function transitTo(aMstateId: number, index: number) {
}
/**
* send trigger
* @param aStateMachine StateMachines
* @param aTriggerName trigger name
*/
//% block="send $aStateMachine $aTriggerName"
//% aStateMachine.defl=StateMachines.M0
//% aTriggerName.defl="e"
//% weight=95
//% group="Command"
export function send(aStateMachine: StateMachines, aTriggerName: string) {
}
/**
* send trigger with args
* @param aStateMachine StateMachines
* @param aTriggerName trigger name
* @param aTriggerArgs args
*/
//% block="send $aStateMachine $aTriggerName $aTriggerArgs"
//% aStateMachine.defl=StateMachines.M0
//% aTriggerName.defl="e"
//% weight=90
//% group="Command"
//% advanced=true
export function sendWith(aStateMachine: StateMachines, aTriggerName: string,
aTriggerArgs: number[]
) {
}
/**
* start state machine
* @param aStateMachine StateMachines
* @param aStateName default state name
*/
//% block="start $aStateMachine $aStateName"
//% aStateMachine.defl=StateMachines.M0
//% aStateName.defl="a"
//% weight=80
//% group="Command"
export function start(aStateMachine: StateMachines, aStateName: string) {
}
/**
* export UML, PlantUML
* PlantUML Web server: http://www.plantuml.com/plantuml/
* @param aStateMachine
* @param aStateName default state
*/
//% block="UML $aStateMachine $aStateName"
//% aStateMachine.defl=StateMachines.M0
//% aStateName.defl="a"
//% weight=70
//% group="Command"
//% shim=mstate::simu_export_uml
//% advanced=true
export function exportUml(aStateMachine: StateMachines, aStateName: string) {
}
/**
* UML state
* @param aMachine machine ID
* @param aStateName state name
*/
//% block
//% shim=mstate::simu_state_uml
//% blockHidden=true
//% advanced=true
export function _simuStateUml(aMachine: number, aStateName: string) {
}
/**
* UML transition
* @param aMachine machine ID
* @param aState state ID
* @param aTransList array of next state name
*/
//% block
//% shim=mstate::simu_transition_uml
//% blockHidden=true
//% advanced=true
export function _simuTransitionUml(aMachine: number, aState: number,
aTransList: string[]
) {
}
/**
* convert id (number) to state/trigger name (string)
* @param id machine-state id or machine-trigger id
* @returns state name (string) or trigger name (string): "[<id>]" if undefined
*/
//% block
//% shim=mstate::simu_conv_name
//% blockHidden=true
//% advanced=true
export function _simuConvName(id: number): string {
}
}
課題2. 説明の記述方法
従来は、状態名称に区切り文字で、区切ってUML状態遷移図の説明を記述していた。
その為、状態名称の可読性が失われたり、micro:bit本体での実行時に不具合が生じたりしていた。
それを、新たに追加したブロックで説明を記述するようにした。
説明記述ブロックに続けて、宣言ブロックを配置すると、その宣言ブロックの状態または遷移の説明となる。
対応する宣言ブロック
説明記述ブロックは、次の宣言ブロックに対応します。
on entry
on do
on exit
transition
UML | 従来版 | 対策版 |
---|---|---|
|
ソースコード(ブロック定義)
enum StateMachines {
M0 = 0,
M1,
M2,
M3,
M4,
M5
}
/**
* mstate blocks
* Defining blocks: https://makecode.com/defining-blocks
* Playground: https://makecode.com/playground
* icon: a Unicode identifier for an icon from the Font Awesome icon set.
* http://fontawesome.io/icons
*/
//% weight=100 color="#4C97FF" icon="\uf362"
//% groups="['Command', 'Declare', 'Transit']"
namespace mstate {
/**
* convert state/trigger name (string) to id (number): new id if undefined
* @param aStateMachine StateMachines
* @param name state name (string) or trigger name (string)
* @returns machine-state id or machine-trigger id
*/
//% block="id of $aStateMachine $name"
//% aStateMachine.defl=StateMachines.M0
//% name.defl="a"
//% weight=210
//% advanced=true
export function convId(aStateMachine: StateMachines, name: string): number {
}
/**
* Internal event settings
* @param aStateMachine StateMachines
* @param eventId Event ID (default: 32868 = 32768 + 100)
* @param ms Event loop interval (default: 100ms)
*/
//% block="settings $aStateMachine event ID: $eventId every: $ms ms"
//% aStateMachine.defl=StateMachines.M0
//% eventId.defl=32768
//% ms.shadow="timePicker"
//% ms.defl=100
//% weight=190
//% advanced=true
export function settingsMachineEvent(aStateMachine: StateMachines, eventId: number,
ms: number
) {
}
/**
* define state
* @param aStateMachine StateMachines
* @param aStateName state name
* @param body code to run, (mstateId: machine-state ID)
*/
//% block="define $aStateMachine $mstateId to $aStateName"
//% aStateMachine.defl=StateMachines.M0
//% aStateName.defl="a"
//% draggableParameters="reporter"
//% weight=180
//% group="Declare"
export function defineState(aStateMachine: StateMachines, aStateName: string,
body: (mstateId: number) => void
) {
}
/**
* declare ENTRY action.
* @param machine-state ID
* @param body code to run
*/
//% block="mstate $aMstateId on entry"
//% $aMstateId.defl=0
//% handlerStatement
//% weight=170
//% group="Declare"
export function declareEntry(aMstateId: number,
body: () => void
) {
}
/**
* declare DO activity.
* @param machine-state ID
* @param aEvery interval time (milliseconds)
* @param body code to run
*/
//% block="mstate $aMstateId on do every $aEvery ms"
//% aMstateId.defl=0
//% aEvery.shadow="timePicker"
//% handlerStatement
//% weight=160
//% group="Declare"
export function declareDo(aMstateId: number, aEvery: number,
body: () => void
) {
}
/**
* declare EXIT action.
* @param machine-state ID
* @param body code to run
*/
//% block="mstate $aMstateId on exit"
//% aMstateId.defl=0
//% handlerStatement
//% weight=150
//% group="Declare"
export function declareExit(aMstateId: number,
body: () => void
) {
}
/**
* declare simple transition.
* @param machine-state ID
* @param aTriggerName trigger name
* @param aToName next state nam
*/
//% block="mstate $aMstateId trasition when $aTriggerName to $aToName"
//% aMstateId.defl=0
//% aTriggerName.defl="e"
//% aToName.defl="a"
//% inlineInputMode=inline
//% weight=140
//% group="Transition"
export function declareSimpleTransition(aMstateId: number,
aTriggerName: string, aToName: string
) {
}
/**
* declare timeouted transition.
* @param machine-state ID
* @param aMs timeout (ms)
* @param aToName next state name
*/
//% block="mstate $aMstateId trasition timeouted $aMs to $aToName"
//% aMstateId.defl=0
//% aMs.shadow="timePicker"
//% aToName.defl="a"
//% inlineInputMode=inline
//% weight=130
//% group="Transition"
export function declareTimeoutedTransition(aMstateId: number,
aMs: number, aToName: string
) {
}
/**
* declare custom transition.
* @param machine-state ID
* @param aTriggerName trigger name
* @param aTransList array of next state name
* @param body code to run
*/
//% block="mstate $aMstateId trasition when $aTriggerName $args to $aTransList"
//% aMstateId.defl=0
//% aTriggerName.defl="e"
//% draggableParameters="reporter"
//% handlerStatement
//% weight=120
//% group="Transition"
export function declareCustomTransition(aMstateId: number,
aTriggerName: string, aTransList: string[],
body: () => void
) {
}
/**
* is timeouted.
* @param machine-state ID, as machine ID
* @param aMs timeout (milliseconds)
*/
//% block="mstate $aMstateId timeouted $aMs"
//% aMstateId.defl=0
//% aMs.shadow="timePicker"
//% weight=110
//% group="Transition"
export function isTimeouted(aMstateId: number, aMs: number): boolean {
}
/**
* trigger args.
* @param machine-state ID, as machine ID
* @returns trigger args
*/
//% block="mstate $aMstateId trigger args"
//% aMstateId.defl=0
//% weight=105
//% group="Transition"
//% advanced=true
export function getTriggerArgs(aMstateId: number): number[] {
}
/**
* transit to.
* @param machine-state ID, as machine ID
* @param index states index]
*/
//% block="mstate $aMstateId transit at $index"
//% aMstateId.defl=0
//% index.defl=0
//% weight=100
//% group="Transition"
export function transitTo(aMstateId: number, index: number) {
}
/**
* send trigger
* @param aStateMachine StateMachines
* @param aTriggerName trigger name
*/
//% block="send $aStateMachine $aTriggerName"
//% aStateMachine.defl=StateMachines.M0
//% aTriggerName.defl="e"
//% weight=95
//% group="Command"
export function send(aStateMachine: StateMachines, aTriggerName: string) {
}
/**
* send trigger with args
* @param aStateMachine StateMachines
* @param aTriggerName trigger name
* @param aTriggerArgs args
*/
//% block="send $aStateMachine $aTriggerName $aTriggerArgs"
//% aStateMachine.defl=StateMachines.M0
//% aTriggerName.defl="e"
//% weight=90
//% group="Command"
//% advanced=true
export function sendWith(aStateMachine: StateMachines, aTriggerName: string,
aTriggerArgs: number[]
) {
}
/**
* start state machine
* @param aStateMachine StateMachines
* @param aStateName default state name
*/
//% block="start $aStateMachine $aStateName"
//% aStateMachine.defl=StateMachines.M0
//% aStateName.defl="a"
//% weight=80
//% group="Command"
export function start(aStateMachine: StateMachines, aStateName: string) {
}
/**
* export UML, PlantUML
* PlantUML Web server: http://www.plantuml.com/plantuml/
* @param aStateMachine
* @param aStateName default state
*/
//% block="UML $aStateMachine $aStateName"
//% aStateMachine.defl=StateMachines.M0
//% aStateName.defl="a"
//% weight=70
//% group="Command"
//% shim=mstate::simu_export_uml
//% advanced=true
export function exportUml(aStateMachine: StateMachines, aStateName: string) {
}
/**
* description UML, PlantUML
* PlantUML Web server: http://www.plantuml.com/plantuml/
* @param aDescription
*/
//% block="description $aDescription"
//% aDescription.defl="(description)"
//% weight=60
//% group="Command"
//% shim=mstate::simu_description_uml
//% advanced=true
export function descriptionUml(aDescription: string) {
}
/**
* UML state
* @param aMachine machine ID
* @param aStateName state name
*/
//% block
//% shim=mstate::simu_state_uml
//% blockHidden=true
//% advanced=true
export function _simuStateUml(aMachine: number, aStateName: string) {
}
/**
* UML transition
* @param aMachine machine ID
* @param aState state ID
* @param aTransList array of next state name
*/
//% block
//% shim=mstate::simu_transition_uml
//% blockHidden=true
//% advanced=true
export function _simuTransitionUml(aMachine: number, aState: number,
aTransList: string[]
) {
}
/**
* convert id (number) to state/trigger name (string)
* @param id machine-state id or machine-trigger id
* @returns state name (string) or trigger name (string): "[<id>]" if undefined
*/
//% block
//% shim=mstate::simu_conv_name
//% blockHidden=true
//% advanced=true
export function _simuConvName(id: number): string {
}
}
課題3. 複数の遷移先(説明の記述)
複数の遷移先がある場合、それぞれの遷移に説明を記述できるようにする為、説明記述ブロックの引数を配列にする(遷移先の配列と順序を合わせる)。
また、説明記述ブロックの引数配列化に伴い、状態の宣言ブロックに対しては、UML出力時に、その要素毎に改行した説明文字列を出力する(改行コード \n
)。
UML | 対策版 |
---|---|
|
ソースコード(ブロック定義)
enum StateMachines {
M0 = 0,
M1,
M2,
M3,
M4,
M5
}
/**
* mstate blocks
* Defining blocks: https://makecode.com/defining-blocks
* Playground: https://makecode.com/playground
* icon: a Unicode identifier for an icon from the Font Awesome icon set.
* http://fontawesome.io/icons
*/
//% weight=100 color="#4C97FF" icon="\uf362"
//% groups="['Command', 'Declare', 'Transit']"
namespace mstate {
/**
* convert state/trigger name (string) to id (number): new id if undefined
* @param aStateMachine StateMachines
* @param name state name (string) or trigger name (string)
* @returns machine-state id or machine-trigger id
*/
//% block="id of $aStateMachine $name"
//% aStateMachine.defl=StateMachines.M0
//% name.defl="a"
//% weight=210
//% advanced=true
export function convId(aStateMachine: StateMachines, name: string): number {
}
/**
* Internal event settings
* @param aStateMachine StateMachines
* @param eventId Event ID (default: 32868 = 32768 + 100)
* @param ms Event loop interval (default: 100ms)
*/
//% block="settings $aStateMachine event ID: $eventId every: $ms ms"
//% aStateMachine.defl=StateMachines.M0
//% eventId.defl=32768
//% ms.shadow="timePicker"
//% ms.defl=100
//% weight=190
//% advanced=true
export function settingsMachineEvent(aStateMachine: StateMachines, eventId: number,
ms: number
) {
}
/**
* define state
* @param aStateMachine StateMachines
* @param aStateName state name
* @param body code to run, (mstateId: machine-state ID)
*/
//% block="define $aStateMachine $mstateId to $aStateName"
//% aStateMachine.defl=StateMachines.M0
//% aStateName.defl="a"
//% draggableParameters="reporter"
//% weight=180
//% group="Declare"
export function defineState(aStateMachine: StateMachines, aStateName: string,
body: (mstateId: number) => void
) {
}
/**
* declare ENTRY action.
* @param machine-state ID
* @param body code to run
*/
//% block="mstate $aMstateId on entry"
//% $aMstateId.defl=0
//% handlerStatement
//% weight=170
//% group="Declare"
export function declareEntry(aMstateId: number,
body: () => void
) {
}
/**
* declare DO activity.
* @param machine-state ID
* @param aEvery interval time (milliseconds)
* @param body code to run
*/
//% block="mstate $aMstateId on do every $aEvery ms"
//% aMstateId.defl=0
//% aEvery.shadow="timePicker"
//% handlerStatement
//% weight=160
//% group="Declare"
export function declareDo(aMstateId: number, aEvery: number,
body: () => void
) {
}
/**
* declare EXIT action.
* @param machine-state ID
* @param body code to run
*/
//% block="mstate $aMstateId on exit"
//% aMstateId.defl=0
//% handlerStatement
//% weight=150
//% group="Declare"
export function declareExit(aMstateId: number,
body: () => void
) {
}
/**
* declare simple transition.
* @param machine-state ID
* @param aTriggerName trigger name
* @param aToName next state nam
*/
//% block="mstate $aMstateId trasition when $aTriggerName to $aToName"
//% aMstateId.defl=0
//% aTriggerName.defl="e"
//% aToName.defl="a"
//% inlineInputMode=inline
//% weight=140
//% group="Transition"
export function declareSimpleTransition(aMstateId: number,
aTriggerName: string, aToName: string
) {
}
/**
* declare timeouted transition.
* @param machine-state ID
* @param aMs timeout (ms)
* @param aToName next state name
*/
//% block="mstate $aMstateId trasition timeouted $aMs to $aToName"
//% aMstateId.defl=0
//% aMs.shadow="timePicker"
//% aToName.defl="a"
//% inlineInputMode=inline
//% weight=130
//% group="Transition"
export function declareTimeoutedTransition(aMstateId: number,
aMs: number, aToName: string
) {
}
/**
* declare custom transition.
* @param machine-state ID
* @param aTriggerName trigger name
* @param aTransList array of next state name
* @param body code to run
*/
//% block="mstate $aMstateId trasition when $aTriggerName $args to $aTransList"
//% aMstateId.defl=0
//% aTriggerName.defl="e"
//% draggableParameters="reporter"
//% handlerStatement
//% weight=120
//% group="Transition"
export function declareCustomTransition(aMstateId: number,
aTriggerName: string, aTransList: string[],
body: () => void
) {
}
/**
* is timeouted.
* @param machine-state ID, as machine ID
* @param aMs timeout (milliseconds)
*/
//% block="mstate $aMstateId timeouted $aMs"
//% aMstateId.defl=0
//% aMs.shadow="timePicker"
//% weight=110
//% group="Transition"
export function isTimeouted(aMstateId: number, aMs: number): boolean {
}
/**
* trigger args.
* @param machine-state ID, as machine ID
* @returns trigger args
*/
//% block="mstate $aMstateId trigger args"
//% aMstateId.defl=0
//% weight=105
//% group="Transition"
//% advanced=true
export function getTriggerArgs(aMstateId: number): number[] {
}
/**
* transit to.
* @param machine-state ID, as machine ID
* @param index states index]
*/
//% block="mstate $aMstateId transit at $index"
//% aMstateId.defl=0
//% index.defl=0
//% weight=100
//% group="Transition"
export function transitTo(aMstateId: number, index: number) {
}
/**
* send trigger
* @param aStateMachine StateMachines
* @param aTriggerName trigger name
*/
//% block="send $aStateMachine $aTriggerName"
//% aStateMachine.defl=StateMachines.M0
//% aTriggerName.defl="e"
//% weight=95
//% group="Command"
export function send(aStateMachine: StateMachines, aTriggerName: string) {
}
/**
* send trigger with args
* @param aStateMachine StateMachines
* @param aTriggerName trigger name
* @param aTriggerArgs args
*/
//% block="send $aStateMachine $aTriggerName $aTriggerArgs"
//% aStateMachine.defl=StateMachines.M0
//% aTriggerName.defl="e"
//% weight=90
//% group="Command"
//% advanced=true
export function sendWith(aStateMachine: StateMachines, aTriggerName: string,
aTriggerArgs: number[]
) {
}
/**
* start state machine
* @param aStateMachine StateMachines
* @param aStateName default state name
*/
//% block="start $aStateMachine $aStateName"
//% aStateMachine.defl=StateMachines.M0
//% aStateName.defl="a"
//% weight=80
//% group="Command"
export function start(aStateMachine: StateMachines, aStateName: string) {
}
/**
* export UML, PlantUML
* PlantUML Web server: http://www.plantuml.com/plantuml/
* @param aStateMachine
* @param aStateName default state
*/
//% block="UML $aStateMachine $aStateName"
//% aStateMachine.defl=StateMachines.M0
//% aStateName.defl="a"
//% weight=70
//% group="Command"
//% shim=mstate::simu_export_uml
//% advanced=true
export function exportUml(aStateMachine: StateMachines, aStateName: string) {
}
/**
* description UML, PlantUML
* PlantUML Web server: http://www.plantuml.com/plantuml/
* @param aDescription
*/
//% block="description $aDescription"
//% aDescription.defl="(description)"
//% weight=60
//% group="Command"
//% shim=mstate::simu_description_uml
//% advanced=true
export function descriptionUml(aDescription: string) {
}
/**
* description UML, PlantUML
* PlantUML Web server: http://www.plantuml.com/plantuml/
* @param aDescription
*/
//% block="description $aDescriptionList"
//% weight=50
//% group="Command"
//% shim=mstate::simu_descriptions_uml
//% advanced=true
export function descriptionsUml(aDescriptionList: string[]) {
}
/**
* UML state
* @param aMachine machine ID
* @param aStateName state name
*/
//% block
//% shim=mstate::simu_state_uml
//% blockHidden=true
//% advanced=true
export function _simuStateUml(aMachine: number, aStateName: string) {
}
/**
* UML transition
* @param aMachine machine ID
* @param aState state ID
* @param aTransList array of next state name
*/
//% block
//% shim=mstate::simu_transition_uml
//% blockHidden=true
//% advanced=true
export function _simuTransitionUml(aMachine: number, aState: number,
aTransList: string[]
) {
}
/**
* convert id (number) to state/trigger name (string)
* @param id machine-state id or machine-trigger id
* @returns state name (string) or trigger name (string): "[<id>]" if undefined
*/
//% block
//% shim=mstate::simu_conv_name
//% blockHidden=true
//% advanced=true
export function _simuConvName(id: number): string {
}
}
課題4. イベント依存
pxt-mstateでは、状態遷移の判定とその実行をmicro:bitのイベント(uBit.messageBus)に依存している。
このイベント処理部分を mcontroller
名前空間の関数群として抜きだし、他の実行環境でも容易に実装できるよう、差し替え可能にする(将来的には抽象クラスとして実現したい)。
/**
* controller - micro:bit
*/
export namespace mcontroller {
/**
* idle update
* @param machineId machine ID
*/
function _idleUpdate(machineId: number) {
control.raiseEvent(MSTATE_BUS_ID.MSTATE_ID_UPDATE, machineId)
}
/**
* create StateMachine
* @param machineId machine ID
* @returns instance of StateMachine
*/
function _createNewStateMacnhe(machineId: number) {
return new mmachine.StateMachine(machineId, function () {
_idleUpdate(machineId)
})
}
}
課題5. ポーリング間隔
(保留)
時間待ちループの経過時間の取得もmicro:bitに依存しているため、外部タイマーとして外出しとし、差し替え可能にしたい。それに合わせて、タイムアウトによるトランジション方式も見直したい。
まとめ
5つの課題のうち、4つの課題を解決し、ver.0.8.3以降 で対応した。
残課題は、次の機会に対応する。
# | 課題 | 結果 | 残課題 |
---|---|---|---|
1 | machine/state | 解決 | |
2 | 説明の記述方法 | 解決 | |
3 | 複数の遷移先(説明記述) | 解決 | |
4 | イベント依存 | 解決 | 抽象クラス化 |
5 | ポーリング間隔 | 保留 | 外部タイマー化 |