// Text of project Comms FSM written on 4/25/97 at 1:28 PM // Beginning of file protoEvent // Before Script for "_userproto000" // Newton Developer Technical Support Sample Code // protoEvent - An NTK Finite State Machine User Proto // by Jim Schram, Newton Developer Technical Support // Copyright ©1996 Apple Computer, Inc. All rights reserved. // // You may incorporate this sample code into your applications without // restriction. This sample code has been provided "AS IS" and the // responsibility for its operation is 100% yours. You are not // permitted to modify and redistribute the source as "DTS Sample Code." // If you are going to re-distribute the source, we require that you // make it clear in the source that the code was descended from // Apple-provided sample code, but that you've made changes. _userproto000 := {viewBounds: {left: 8, top: 16, right: -8, bottom: 32}, viewJustify: 8405040, _proto: @218 }; constant |layout_protoEvent| := _userproto000; // End of file protoEvent // Beginning of file protoState // Before Script for "_userproto001" // Newton Developer Technical Support Sample Code // protoState - An NTK Finite State Machine User Proto // by Jim Schram, Newton Developer Technical Support // Copyright ©1996 Apple Computer, Inc. All rights reserved. // // You may incorporate this sample code into your applications without // restriction. This sample code has been provided "AS IS" and the // responsibility for its operation is 100% yours. You are not // permitted to modify and redistribute the source as "DTS Sample Code." // If you are going to re-distribute the source, we require that you // make it clear in the source that the code was descended from // Apple-provided sample code, but that you've made changes. _userproto001 := {viewBounds: {left: 8, top: 16, right: -8, bottom: 88}, viewJustify: 8396848, _proto: @473 }; constant |layout_protoState| := _userproto001; // End of file protoState // Beginning of file protoFSM // Before Script for "_userproto002" // Newton Developer Technical Support Sample Code // protoFSM - An NTK Finite State Machine User Proto // by Jim Schram, Newton Developer Technical Support // Copyright ©1996 Apple Computer, Inc. All rights reserved. // // You may incorporate this sample code into your applications without // restriction. This sample code has been provided "AS IS" and the // responsibility for its operation is 100% yours. You are not // permitted to modify and redistribute the source as "DTS Sample Code." // If you are going to re-distribute the source, we require that you // make it clear in the source that the code was descended from // Apple-provided sample code, but that you've made changes. // kFSMBuildTemplateFunc - compile time only // // Function to call at compile time to create a FSM from a text file definition or other non-layout source. // Performs basic sanity checking, constructs a protoFSM user template, and returns it. // // // DefConst ( 'kMyFSMTemplate, // call kFSMBuildTemplateFunc with ( 'myFSM, // symbol = required name of this FSM // nil, // frame or nil = optional context frame // Home & "myFSM.f", // string or frame = required name of frame definition file to load, or frame definition // GetLayout("protoFSM") // frame = required reference to protoFSM engine, or other engine // ) // ); // // // fsm := kMyFSMTemplate:Instantiate(); // kFSMBuildTemplateFunc := func(name, context, definition, engine) begin local fsmSymbol := name; if not fsmSymbol then begin fsmSymbol := 'unknown; print("A protoFSM implementation is unnamed (kFSMBuildTemplateFunc requires the name parameter)."); end; if not engine then begin print("The '|" & fsmSymbol & "| protoFSM engine is invalid."); return; end; definitionFrame := if IsInstance(definition, 'string) then Load(definition) else definition; if not IsInstance(definitionFrame, 'frame) then begin print("The '|" & fsmSymbol & "| protoFSM definition is invalid."); return; end; if not definitionFrame.Genesis then print("The '|" & fsmSymbol & "| protoFSM implementation is missing the required '|Genesis| state."); local templateFrame := if IsInstance(context, 'frame) then context else {}; templateFrame._proto := engine; templateFrame.declareSelf := fsmSymbol; templateFrame.fsm_private_states := definitionFrame; if not kDebugOn then // GoToState is a debug-only function! begin RemoveSlot(templateFrame._proto, 'GoToState); RemoveSlot(templateFrame, 'GoToState); end; RemoveSlot(templateFrame._proto, '_proto); RemoveSlot(templateFrame._proto, 'viewBounds); templateFrame; end; // kFSMCleanUpFunc - compile time only // // Function to call in the afterScript of your FSM layout. // Converts NTK layout data structures into "pure" FSM data structures used by protoFSM. // // Example: // // // call kFSMCleanUpFunc with (thisView); // let's assume the filename of this layout is "myFSM.t" // // // fsm := GetLayout("myFSM.t"):Instantiate(); // kFSMCleanUpFunc := func(fsmFrame) begin local fsmSymbol, stateSymbol, eventSymbol, hasGenesisState; RemoveSlot(fsmFrame._proto, '_proto); RemoveSlot(fsmFrame._proto, 'viewBounds); RemoveSlot(fsmFrame, 'viewBounds); RemoveSlot(fsmFrame, 'viewJustify); fsmFrame.fsm_private_states := { }; if not fsmSymbol := GetSlot(fsmFrame, 'declareSelf) then begin fsmSymbol := 'unknown; print("A protoFSM implementation is unnamed (you forgot the declareSelf slot)."); end; if fsmFrame.stepChildren then foreach stateFrame in fsmFrame.stepChildren do begin RemoveSlot(stateFrame, '_proto); RemoveSlot(stateFrame, 'viewBounds); RemoveSlot(stateFrame, 'viewJustify); if not stateSymbol := GetSlot(stateFrame, 'declareSelf) then begin stateSymbol := 'unknown; print("A protoState in the '|" & fsmSymbol & "| protoFSM implementation is unnamed (you forgot the declareSelf slot)."); end; if fsmFrame.fsm_private_states.(stateSymbol) then print("The '|" & stateSymbol & "| protoState in the '|" & fsmSymbol & "| protoFSM implementation already exists (duplicate declareSelf slot value)."); else fsmFrame.fsm_private_states.(stateSymbol) := stateFrame; if stateFrame.stepChildren then foreach eventFrame in stateFrame.stepChildren do begin RemoveSlot(eventFrame, '_proto); RemoveSlot(eventFrame, 'viewBounds); RemoveSlot(eventFrame, 'viewJustify); if not eventSymbol := GetSlot(eventFrame, 'declareSelf) then begin eventSymbol := 'unknown; print("A protoEvent in the '|" & stateSymbol & "| state of the '|" & fsmSymbol & "| protoFSM implementation is unnamed (you forgot the declareSelf slot)."); end; if stateFrame.(eventSymbol) then print("The '|" & eventSymbol & "| protoEvent in the '|" & stateSymbol & "| protoState in the '|" & fsmSymbol & "| protoFSM implementation already exists (duplicate declareSelf slot value)."); else stateFrame.(eventSymbol) := eventFrame; RemoveSlot(eventFrame, 'declareSelf); end; RemoveSlot(stateFrame, 'declareSelf); RemoveSlot(stateFrame, 'stepChildren); hasGenesisState := hasGenesisState or stateSymbol = 'Genesis; end; if not hasGenesisState then print("The '|" & fsmSymbol & "| protoFSM implementation is missing the required '|Genesis| state."); if not kDebugOn then // GoToState is a debug-only function! begin RemoveSlot(fsmFrame._proto, 'GoToState); RemoveSlot(fsmFrame, 'GoToState); end; RemoveSlot(fsmFrame, 'stepChildren); nil; end _userproto002 := {viewBounds: {left: 8, top: 8, right: 232, bottom: 280}, DoEvent: func(eventSymbol, paramArray) // SELF can be anything that inherits to the finite state machine instance frame begin local x := :?DoEvent_Check('|protoFSM:DoEvent|); if not x then return; if kDebugOn then if paramArray and PrimClassOf(paramArray) <> 'Array then Throw('|evt.ex.msg|, "protoFSM:DoEvent 2nd argument must be Nil or Array"); x.pendingEventQueue:EnQueue(eventSymbol); x.pendingParamsQueue:EnQueue(paramArray); if not x.busy then begin x.busy := true; AddDelayedSend(x.fsm, 'DoEvent_Loop, nil, x.turtle); end; nil; end, instantiate: // SELF is the finite state machine template frame, e.g.: // // local fsm := GetLayout("myFSM"):Instantiate(); // // "myFSM" is assumed to be a layout based on protoFSM, func() begin local obj := { _proto: self, fsm: nil, currentStateFrame: nil, currentEventFrame: nil, fsm_private_context: { fsm: nil, turtle: 1, level: 0, busy: nil, waitView: nil, waitAborted: nil, isNewPendingState: true, pendingState: 'Genesis, pendingEventQueue: QueueTemplate:Instantiate(), pendingParamsQueue: QueueTemplate:Instantiate(), currentState: nil, currentEvent: nil, currentParams: nil, }, }; obj.currentStateFrame := { _proto: obj.fsm_private_states.Genesis, _parent: obj, }; obj.fsm := obj.fsm_private_context.fsm := obj; end, dispose: func() // SELF should be the finite state machine instance frame begin if not fsm_private_context then return; fsm_private_context.pendingEventQueue:Reset(); fsm_private_context.pendingParamsQueue:Reset(); foreach slot, value in fsm_private_context do fsm_private_context.(slot) := nil; fsm := currentStateFrame := currentEventFrame := fsm_private_context := nil; nil; // guaranteed to return nil so that the caller can conveniently nil out the FSM container variable end, DoEvent_Loop: func() // SELF is the finite state machine instance frame begin repeat local x := :?DoEvent_Check('|protoFSM:DoEvent_Loop|); if not x then return; local ok := nil; local pendingStateFrame := nil; if x.pendingState then if fsm_private_states.(x.pendingState) then if fsm_private_states.(x.pendingState).(x.pendingEventQueue:Peek()) then ok := true; else begin if kDebugOn then :?DebugFSM('UnknownEvent, x.pendingState, x.pendingEventQueue:Peek(), x.pendingParamsQueue:Peek()); // ignore if event not programmed end; else begin if kDebugOn then :?DebugFSM('UnknownState, x.pendingState, x.pendingEventQueue:Peek(), x.pendingParamsQueue:Peek()); // error --> remain in current state end; else begin if kDebugOn then :?DebugFSM('NilState, x.pendingState, x.pendingEventQueue:Peek(), x.pendingParamsQueue:Peek()); // machine halted end; if not ok then begin currentStateFrame := nil; currentEventFrame := nil; x.isNewPendingState := true; x.pendingEventQueue:DeQueue(); // there is a problem with this state or event x.pendingParamsQueue:DeQueue(); // so remove the offending pending queue elements end; else begin x.currentState := x.pendingState; x.currentEvent := x.pendingEventQueue:DeQueue(); x.currentParams := x.pendingParamsQueue:DeQueue(); if x.isNewPendingState then begin x.isNewPendingState := nil; currentStateFrame := { _proto: fsm_private_states.(x.currentState), _parent: self, }; end; currentEventFrame := { _proto: fsm_private_states.(x.currentState).(x.currentEvent), _parent: currentStateFrame, }; if currentEventFrame.Action then begin if kDebugOn then :?TraceFSM('PreAction, x.currentState, x.currentEvent, x.currentParams); x.level := x.level + 1; try Perform(currentEventFrame, 'Action, x.currentParams); onexception |evt.ex| do begin try :?ExceptionHandler(CurrentException()); onexception |evt.ex| do nil; end; x.level := x.level - 1; if kDebugOn then :?TraceFSM('PostAction, x.currentState, x.currentEvent, x.currentParams); end; if currentEventFrame.nextState then begin x.pendingState := currentEventFrame.nextState; x.isNewPendingState := (x.currentState <> x.pendingState); end; if kDebugOn then :?TraceFSM('NextState, x.pendingState, x.pendingEventQueue:Peek(), x.pendingParamsQueue:Peek()); end; if x.waitView // check for terminal state & exit waitView if necessary and x.pendingState and pendingStateFrame := fsm_private_states.(x.pendingState) then if pendingStateFrame.terminal then begin x.pendingEventQueue:Reset(); x.pendingParamsQueue:Reset(); AddDelayedCall( func() if x.waitView then x.waitView:Close(), nil, 1 ); end; x.busy := not x.pendingEventQueue:IsEmpty(); until not(x.busy and currentEventFrame and currentEventFrame.nextNoIdle); if x.busy then AddDelayedSend(self, 'DoEvent_Loop, nil, x.turtle); nil; end, SetSpeed: func(newSpeed) // SELF is the finite state machine instance frame begin fsm_private_context.turtle := newSpeed; end, IsBusy: func() // SELF is the finite state machine instance frame begin fsm_private_context.busy; end, GetSpeed: func() // SELF is the finite state machine instance frame begin fsm_private_context.turtle; end, GoToState: // SELF is the finite state machine instance frame // This function is for DEBUGGING USE ONLY ! ! ! // It is STRIPPED from the resulting package when kDebugOn = nil func(newState) begin local x := fsm_private_context; x.pendingState := newState; x.pendingEventQueue:Reset(); x.pendingParamsQueue:Reset(); nil; end, QueueTemplate: { Instantiate: func() // This is a very simple First-In-First-Out queue { _proto: self, queue: [], }, Reset: func() SetLength(queue, 0), Peek: func() if Length(queue) > 0 then queue[0], // else nil DeQueue: func() if Length(queue) > 0 then // else nil begin local data := queue[0]; RemoveSlot(queue, 0); data; end, EnQueue: func(data) begin AddArraySlot(queue, data); nil; end, GetQueueSize: func() Length(queue), IsEmpty: func() Length(queue) = 0, }, ProtoClone: func(object) begin local f := func native(obj) begin if not IsFrame(obj) or IsFunction(obj) then Throw('|evt.ex.msg|, "ProtoClone only works with frames."); local new := {_proto: obj}; foreach slot, value in obj do if IsFrame(value) and not IsFunction(value) then new.(slot) := call f with (value); new; end; call f with (object); end, WaitForTerminal: func(options) begin local x := fsm_private_context; if x.waitView or x.level <> 0 or x.pendingEventQueue:IsEmpty() then return; x.waitView := BuildContext(waitViewTemplate); x.waitView:SetOwnerContext(x, options); x.waitView:ModalDialog(); x.waitAborted; // return the value of waitAborted (true = user aborted via the status slip, nil = FSM terminal state was reached normally) end, waitViewTemplate: { viewClass: clView, viewFlags: vVisible, viewFormat: vfNone, viewBounds: { left: 0, top: 0, right: 0, bottom: 0, }, statusView: nil, statusViewOptions: nil, fsmContext: nil, aborted: nil, SetOwnerContext: func(owner, options) begin self.statusView := nil; self.statusViewOptions := options; // frame of options the caller of WaitForTerminal is passing us (e.g. progress messages, etc.) self.fsmContext := owner; // the fsm_private_context slot of the FSM self.aborted := nil; end, viewIdleScript: func() begin statusView := BuildContext(statusViewTemplate); statusView:SetOwnerContext(self, statusViewOptions); statusView:ModalDialog(); nil; end, viewSetupDoneScript: func() begin inherited:?ViewSetupDoneScript(); if not statusViewOptions then :SetUpIdle(2000); else if statusViewOptions.delayUntilStatusVisible then :SetUpIdle(if statusViewOptions.delayUntilStatusVisible <= 0 then 1 else statusViewOptions.delayUntilStatusVisible); end, viewQuitScript: func() begin if statusView then statusView:Close(); fsmContext.waitAborted := aborted; fsmContext.waitView := nil; end, statusViewTemplate: { _proto: protoStatusTemplate, initialSetup: nil, waitView: nil, delayUntilAbortTimer: nil, delayUntilAbortVisible: nil, abortButtonText: nil, viewIdleScript: func() begin inherited:?viewIdleScript(); local contents := { name: 'vBarber, values: { barber: true, }, }; if delayUntilAbortVisible then begin delayUntilAbortTimer := delayUntilAbortTimer + 300; if delayUntilAbortTimer > delayUntilAbortVisible then begin delayUntilAbortVisible := nil; contents.values.primary := { text: abortButtonText, script: func() begin waitView.aborted := true; waitView:Close(); end, }; base:ViewSet(contents); return 300; end; end; base:UpdateIndicator(contents); 300; end, viewSetupDoneScript: func() begin inherited:?ViewSetupDoneScript(); :SetUpIdle(100); self.delayUntilAbortTimer := 0; end, SetOwnerContext: func(owner, options) begin self.waitView := owner; self.delayUntilAbortVisible := if options then options.delayUntilAbortVisible else 8000; self.abortButtonText := if options and options.abortButtonText then options.abortButtonText else "Abort"; self.initialSetup := { name: 'vBarber, values: { icon: ROM_routeUpdateBitmap, statusText: if options then options.statusText else "Please wait...", titleText: if options then options.titleText else nil, barber: true, primary: nil, closeBox: nil, }, }; end, }, }, ExceptionHandler: func(exception) begin local x := fsm_private_context; local message := if x then "The following exception occured in event (" & x.currentEvent & ") of state (" & x.currentState & ") of finite state machine (" & x.fsm.declareSelf & "): " else "The following exception occured: "; local exceptionStr := ""; try exceptionStr := :ObjectToString(exception); onexception |evt.ex| do nil; :ExceptionHandler_Notify(message & exceptionStr); nil; end, ObjectToString: // Converts (any?) NewtonScript data type into a string representation. // Follows _proto pointers if the global var printProto is true. // Follows _parent pointers if the global var printParent is true. // Respects the global var printDepth (printDepth < 0 is effectively "infinite depth"). // Respects the global var printLength (printLength < 0 or nil is effectively "infinite length"). // Traps recursive references avoiding endless loops. // Gives each frame and array a "reference number" so backpointer references make sense. // Prints real numbers according to the global var printReal (a string defining the print format, e.g. "%.2f"). // Punts on any exception, like evt.ex.outofmem. // NOTE: This routine is primarily intended for use only during debugging. func(obj) begin constant separator := ", "; constant separatorLen := StrLen(separator); local backIndex := nil; local backList := [nil]; local runProto := GetGlobalVar('printProto) <> nil; local runParent := GetGlobalVar('printParent) <> nil; local floatFormat := GetGlobalVar('printReal); if not IsString(floatFormat) then floatFormat := "%.16e"; local maxDepth := GetGlobalVar('printDepth); if not IsNumber(maxDepth) or maxDepth < 0 then maxDepth := 65535; // arbitrarily large value local maxLength := GetGlobalVar('printLength); if not IsNumber(maxLength) or maxLength < 0 then maxLength := 65535; // arbitrarily large value local p := func native(s) begin if EndsWith(s, separator) then StrMunger(s, StrLen(s) - separatorLen, nil, nil, 0, nil) else s; end; local f := func native(obj, depth) begin local x := 0; ( if IsMagicPtr(obj) then "@+" & RefOf(obj) else if IsFunction(obj) then begin x := GetFunctionArgCount(obj); ParamStr("func(^0 arg^?1|s|)", [x, x = 1]); end else if IsFrame(obj) then if backIndex := LSearch(backList, obj, 1, '|=|, nil) then "<" & backIndex & ">" else begin local s := "{<" & Length(backList) & "> "; AddArraySlot(backList, obj); if depth > maxDepth then s := s & "+" & RefOf(obj); else foreach slot, item in obj do if (x := x + 1) > maxLength then begin s := s & "..."; break; end else s := s & slot & ": " & if (slot = '_parent and not runParent) or (slot = '_proto and not runProto) then "" & separator else call f with (item, depth + 1); call p with (s) & "}"; end else if IsArray(obj) then if backIndex := LSearch(backList, obj, 1, '|=|, nil) then "<" & backIndex & ">" else begin local s := "[<" & Length(backList) & "> " & (if ClassOf(obj) <> 'Array then ClassOf(obj) & ": "); AddArraySlot(backList, obj); if depth > maxDepth then s := s & "+" & RefOf(obj); else foreach item in obj do if (x := x + 1) > maxLength then begin s := s & "..."; break; end else s := s & call f with (item, depth + 1) ; call p with (s) & "]"; end else if IsString(obj) then $" & obj & $" else if IsSymbol(obj) then $' & obj else if IsInteger(obj) then (if obj > 0 then "+" else "") & NumberStr(obj) else if IsNumber(obj) then (if obj > 0 then "+" else "") & FormattedNumberStr(obj, floatFormat) else if IsImmediate(obj) then if not obj then "nil" else if obj = true then "true" else SPrintObject(obj) else if IsBinary(obj) then "<" & ClassOf(obj) & ", length " & Length(obj) & ">" else SPrintObject(obj) ) & separator; end; try call p with (call f with (obj, 0)); onexception |evt.ex.outofmem| do begin backList := nil; ""; end; onexception |evt.ex| do begin backList := nil; ""; end; end, DoEvent_Check: func(where) // This routine checks to see if the FSM has been unexpectedly disposed. That's especially bad if there's a delayed action/call/send about to trigger! begin local x := fsm_private_context; if x then return x; if kDebugOn then :?ExceptionHandler_Notify("An active protoFSM object has mysteriously vanished! Discovered in " & SPrintObject(where) & ". You should consider resetting your Newton device now."); nil; end, ExceptionHandler_Notify: func(message) begin GetRoot():Notify(kNotifyAlert, kAppName, message); if kDebugOn then begin print(message); if GetGlobalVar('BreakOnThrows) then BreakLoop(); end; nil; end, _proto: @218 }; constant |layout_protoFSM| := _userproto002; // End of file protoFSM // Beginning of file CommsFSM // Before Script for "Comms FSM" // Newton Developer Technical Support Sample Code // CommsFSM - An NTK Finite State Machine Implementation // by Jim Schram, Newton Developer Technical Support // Copyright ©1996 Apple Computer, Inc. All rights reserved. // // You may incorporate this sample code into your applications without // restriction. This sample code has been provided "AS IS" and the // responsibility for its operation is 100% yours. You are not // permitted to modify and redistribute the source as "DTS Sample Code." // If you are going to re-distribute the source, we require that you // make it clear in the source that the code was descended from // Apple-provided sample code, but that you've made changes. Comms FSM := { DebugFSM: func(reason, state, event, params) begin local s := "Reason = " & :ObjectToString(reason) & "\nState = " & :ObjectToString(state) & "\nEvent = " & :ObjectToString(event) & "\nParams = " & :ObjectToString(params); :MTrace(s); print(SubstituteChars(s, "\n", "\t")); end, TraceFSM: func(when, state, event, params) begin local s := "When = " & :ObjectToString(when) & "\nState = " & :ObjectToString(state) & "\nEvent = " & :ObjectToString(event) & "\nParams = " & :ObjectToString(params); :MTrace(s); print(SubstituteChars(s, "\n", "\t")); end, MNotifyError: // where = string describing location of error // error = NewtonScript object (e.g. integer, real number, exception frame, etc.) describing the error func(where, error) begin if not error or error = -16005 or fAbort then return; :MNotify("An error occured in " & where & ". Error = " & :ObjectToString(error)); end, MNotify: func(message) begin GetRoot():Notify(kNotifyAlert, kAppName, message); end, MTrace: func(s) begin local base := GetRoot().(kAppSymbol); if base and call kViewIsOpenFunc with (base) and base.vTraceBox and call kViewIsOpenFunc with (base.vTraceBox) then begin SetValue(base.vTraceBox, 'text, s); RefreshViews(); end; end, fState: 'Disconnected, fConnectAction: nil, fEndpoint: nil, fPowerOffState: nil, declareSelf: 'CommsFSM, fAbort: nil, viewBounds: {left: 0, top: 0, right: 192, bottom: 1400}, debug: "Comms FSM" , _proto: _userproto002 }; Genesis := {terminal: true, declareSelf: 'Genesis, viewBounds: {left: 8, top: 16, right: -8, bottom: 56}, debug: "Genesis", _proto: _userproto001 }; AddStepForm(Comms FSM, Genesis); Create := { action: func() begin fsm.fConnectAction := 'Connect; fsm.fState := 'Connecting; fsm.fPowerOffState := nil; fsm.fAbort := nil; fsm.fEndpoint := { _proto: protoBasicEndpoint, _parent: fsm, }; RegPowerOff( kAppSymbol, func(what, why) // we create the closure here so as to set up SELF as the event frame in the closure begin if what = 'okToPowerOff then begin if why <> 'idle // keep the unit awake whenever we're connected or fsm.fState = 'Disconnected then // unless the user or an application explicitly return true; // wants it to sleep end; else if what = 'powerOff then begin if why <> 'idle // if we simply must go to sleep but we're still or fsm.fState <> 'Disconnected then // connected then begin the disconnect process begin fsm.fPowerOffState := 'holdYourHorses; // set a flag to indicate we're powering down :DoEvent('Cancel, nil); return 'holdYourHorses; end; end; nil; // ALWAYS return nil here! end ); :DoEvent('Instantiate, nil); end, nextState: 'Instantiate, declareSelf: 'Create, nextNoIdle: true, debug: "Create", _proto: _userproto000 }; AddStepForm(Genesis, Create); Instantiate := {declareSelf: 'Instantiate, debug: "Instantiate", _proto: _userproto001}; AddStepForm(Comms FSM, Instantiate); Instantiate := { action: func() begin try fEndPoint:Instantiate(fEndPoint, :MBuildConfigOptions()); onexception |evt.ex| do return :DoEvent('InstantiateFailure, [CurrentException()]); :DoEvent('InstantiateSuccess, nil); end, declareSelf: 'Instantiate, MBuildConfigOptions: func() begin [ { label: kCMSAsyncSerial, type: 'service, opCode: opSetRequired, result: nil, }, { label: kCMOSerialIOParms, type: 'option, opCode: opSetRequired, result: nil, form: 'template, data: { arglist: [ k1StopBits, // 1 stop bit kNoParity, // no parity bit k8DataBits, // 8 data bits k19200bps, ], // date rate in bps typelist: ['struct, 'long, // stop bits 'long, // parity 'long, // data bits 'long, ], }, }, // bps { label: kCMOInputFlowControlParms, type: 'option, opCode: opSetRequired, result: nil, form: 'template, data: { arglist: [ unicodeDC1, // xonChar unicodeDC3, // xoffChar nil, // useSoftFlowControl nil, // useHardFlowControl 0, // not needed; returned 0, ], // not needed; returned typelist: ['struct, 'char, // XON character 'char, // XOFF character 'boolean, // software flow control 'boolean, // hardware flow control 'boolean, // hardware flow blocked 'boolean, ], }, }, // software flow blocked { label: kCMOOutputFlowControlParms, type: 'option, opCode: opSetRequired, result: nil, form: 'template, data: { arglist: [ unicodeDC1, // xonChar unicodeDC3, // xoffChar nil, // useSoftFlowControl nil, // useHardFlowControl 0, // not needed; returned 0, ], // not needed; returned typelist: ['struct, 'char, // XON character 'char, // XOFF character 'boolean, // software flow control 'boolean, // hardware flow control 'boolean, // hardware flow blocked 'boolean, ], }, }, // software flow blocked ]; end, nextState: 'Instantiating, debug: "Instantiate", _proto: _userproto000 }; AddStepForm(Instantiate, Instantiate); Abort := {declareSelf: 'Abort, action: func() begin :DoEvent('CleanUp, nil); end, nextState: 'CleanUp, debug: "Abort", _proto: _userproto000 }; AddStepForm(Instantiate, Abort); Cancel := {declareSelf: 'Cancel, action: func() begin fAbort := true; end, debug: "Cancel", _proto: _userproto000 }; AddStepForm(Instantiate, Cancel); Instantiating := {declareSelf: 'Instantiating, debug: "Instantiating", _proto: _userproto001} ; AddStepForm(Comms FSM, Instantiating); Instantiate Success := { action: func() begin if fAbort then return :DoEvent('Abort, nil); :DoEvent('Bind, nil); end, declareSelf: 'InstantiateSuccess, nextState: 'Bind, debug: "Instantiate Success", _proto: _userproto000 }; AddStepForm(Instantiating, Instantiate Success); Instantiate Failure := { action: func(error) begin :MNotifyError("Endpoint Instantiate", error); :DoEvent('CleanUp, nil); end, declareSelf: 'InstantiateFailure, nextState: 'CleanUp, debug: "Instantiate Failure", _proto: _userproto000 }; AddStepForm(Instantiating, Instantiate Failure); Cancel := {declareSelf: 'Cancel, action: func() begin fAbort := true; end, debug: "Cancel", _proto: _userproto000 }; AddStepForm(Instantiating, Cancel); Bind := {declareSelf: 'Bind, debug: "Bind", _proto: _userproto001}; AddStepForm(Comms FSM, Bind); Bind := {declareSelf: 'Bind, action: func() begin try fEndPoint:Bind(:MBuildConfigOptions(), fCompletionSpec); onexception |evt.ex| do :DoEvent('BindFailure, [CurrentException()]); end, fCompletionSpec: { async: true, reqTimeout: kNoTimeout, completionScript: func(ep, options, result) begin if result then ep:DoEvent('BindFailure, [result]); else ep:DoEvent('BindSuccess, nil); end, }, MBuildConfigOptions: func() begin nil; end, nextState: 'Binding, debug: "Bind", _proto: _userproto000 }; AddStepForm(Bind, Bind); Abort := {declareSelf: 'Abort, action: func() begin :DoEvent('Dispose, nil); end, nextState: 'Dispose, debug: "Abort", _proto: _userproto000 }; AddStepForm(Bind, Abort); Cancel := {declareSelf: 'Cancel, action: func() begin fAbort := true; end, debug: "Cancel", _proto: _userproto000 }; AddStepForm(Bind, Cancel); Binding := {declareSelf: 'Binding, debug: "Binding", _proto: _userproto001}; AddStepForm(Comms FSM, Binding); Bind Success := {declareSelf: 'BindSuccess, action: func() begin if fAbort then return :DoEvent('Abort, nil); :DoEvent('Connect, nil); end, nextState: 'Connect, debug: "Bind Success", _proto: _userproto000 }; AddStepForm(Binding, Bind Success); Bind Failure := {declareSelf: 'BindFailure, action: func(error) begin :MNotifyError("Endpoint Bind", error); :DoEvent('Dispose, nil); end, nextState: 'Dispose, debug: "Bind Failure", _proto: _userproto000 }; AddStepForm(Binding, Bind Failure); Cancel := {declareSelf: 'Cancel, action: func() begin fAbort := true; try fEndPoint:Cancel(nil); onexception |evt.ex.comm| do nil; end, debug: "Cancel", _proto: _userproto000 }; AddStepForm(Binding, Cancel); Connect := {declareSelf: 'Connect, debug: "Connect", _proto: _userproto001}; AddStepForm(Comms FSM, Connect); Connect := {declareSelf: 'Connect, action: func() begin if fConnectAction = 'Connect then begin try fEndPoint:Connect(:MBuildConnectConfigOptions(), fCompletionSpec_Connect); onexception |evt.ex| do :DoEvent('ConnectFailure, [CurrentException()]); end; else begin try fEndPoint:Listen(:MBuildListenConfigOptions(), fCompletionSpec_Listen); onexception |evt.ex| do :DoEvent('ListenFailure, [CurrentException()]); end; end, fCompletionSpec_Connect: { async: true, reqTimeout: kNoTimeout, completionScript: func(ep, options, result) begin if result then ep:DoEvent('ConnectFailure, [result]); else ep:DoEvent('ConnectSuccess, nil); end, }, fCompletionSpec_Listen: { async: true, reqTimeout: kNoTimeout, completionScript: func(ep, options, result) begin if result then ep:DoEvent('ListenFailure, [result]); else ep:DoEvent('ListenSuccess, nil); end, }, MBuildListenConfigOptions: func() begin nil; end, MBuildConnectConfigOptions: func() begin nil; end, nextState: 'Connecting, debug: "Connect", _proto: _userproto000 }; AddStepForm(Connect, Connect); Abort := {declareSelf: 'Abort, action: func() begin :DoEvent('UnBind, nil); end, nextState: 'UnBind, debug: "Abort", _proto: _userproto000 }; AddStepForm(Connect, Abort); Cancel := {declareSelf: 'Cancel, action: func() begin fAbort := true; end, debug: "Cancel", _proto: _userproto000 }; AddStepForm(Connect, Cancel); Connecting := {declareSelf: 'Connecting, viewBounds: {left: 8, top: 16, right: -8, bottom: 120}, debug: "Connecting" , _proto: _userproto001 }; AddStepForm(Comms FSM, Connecting); Connect Success := { action: func() begin fState := 'Connected; if fAbort then return :DoEvent('Disconnect, nil); :DoEvent('Connected, nil); end, declareSelf: 'ConnectSuccess, nextState: 'Connected, debug: "Connect Success", _proto: _userproto000 }; AddStepForm(Connecting, Connect Success); Connect Failure := { action: func(error) begin :MNotifyError("Endpoint Connect", error); :DoEvent('UnBind, nil); end, declareSelf: 'ConnectFailure, nextState: 'UnBind, debug: "Connect Failure", _proto: _userproto000 }; AddStepForm(Connecting, Connect Failure); Listen Success := { action: func() begin if fAbort then return :DoEvent('Abort, nil); :DoEvent('Accept, nil); end, declareSelf: 'ListenSuccess, nextState: 'Accept, debug: "Listen Success", _proto: _userproto000 }; AddStepForm(Connecting, Listen Success); Listen Failure := { action: func(error) begin :MNotifyError("Endpoint Listen", error); :DoEvent('UnBind, nil); end, declareSelf: 'ListenFailure, nextState: 'UnBind, debug: "Listen Failure", _proto: _userproto000 }; AddStepForm(Connecting, Listen Failure); Cancel := {declareSelf: 'Cancel, action: func() begin fAbort := true; try fEndPoint:Cancel(nil); onexception |evt.ex.comm| do nil; end, debug: "Cancel", _proto: _userproto000 }; AddStepForm(Connecting, Cancel); Accept := {declareSelf: 'Accept, debug: "Accept", _proto: _userproto001}; AddStepForm(Comms FSM, Accept); Accept := {declareSelf: 'Accept, action: func() begin try fEndPoint:Accept(nil, fCompletionSpec); onexception |evt.ex| do :DoEvent('AcceptFailure, [CurrentException()]); end, fCompletionSpec: { async: true, reqTimeout: kNoTimeout, completionScript: func(ep, options, result) begin if result then ep:DoEvent('AcceptFailure, [result]); else ep:DoEvent('AcceptSuccess, nil); end, }, nextState: 'Accepting, debug: "Accept", _proto: _userproto000 }; AddStepForm(Accept, Accept); Abort := {declareSelf: 'Abort, action: func() begin :DoEvent('Disconnect, nil); end, nextState: 'Disconnect, debug: "Abort", _proto: _userproto000 }; AddStepForm(Accept, Abort); Cancel := {declareSelf: 'Cancel, action: func() begin fAbort := true; end, debug: "Cancel", _proto: _userproto000 }; AddStepForm(Accept, Cancel); Accepting := {declareSelf: 'Accepting, debug: "Accepting", _proto: _userproto001}; AddStepForm(Comms FSM, Accepting); Accept Success := { action: func() begin fState := 'Connected; if fAbort then return :DoEvent('Disconnect, nil); :DoEvent('Connected, nil); end, declareSelf: 'AcceptSuccess, nextState: 'Connected, debug: "Accept Success", _proto: _userproto000 }; AddStepForm(Accepting, Accept Success); Accept Failure := { action: func(error) begin :MNotifyError("Endpoint Accept", error); :DoEvent('UnBind, nil); end, declareSelf: 'AcceptFailure, nextState: 'UnBind, debug: "Accept Failure", _proto: _userproto000 }; AddStepForm(Accepting, Accept Failure); Cancel := {declareSelf: 'Cancel, action: func() begin fAbort := true; try fEndPoint:Cancel(nil); onexception |evt.ex.comm| do nil; end, debug: "Cancel", _proto: _userproto000 }; AddStepForm(Accepting, Cancel); Connected := {declareSelf: 'Connected, debug: "Connected", _proto: _userproto001}; AddStepForm(Comms FSM, Connected); Connected := { action: func() begin if fAbort then return :DoEvent('Disconnect, nil); // Send message to app indicating connection has been established. end, declareSelf: 'Connected, debug: "Connected", _proto: _userproto000 }; AddStepForm(Connected, Connected); Disconnect := { action: func() begin fState := 'Disconnecting; fAbort := true; try fEndPoint:Disconnect(true, fCompletionSpec); onexception |evt.ex| do :DoEvent('DisconnectFailure, [CurrentException()]); end, declareSelf: 'Disconnect, nextState: 'Disconnecting, fCompletionSpec: { async: true, reqTimeout: kNoTimeout, completionScript: func(ep, options, result) begin if result then ep:DoEvent('DisconnectFailure, [result]); else ep:DoEvent('DisconnectSuccess, nil); end, }, debug: "Disconnect", _proto: _userproto000 }; AddStepForm(Connected, Disconnect); Cancel := {declareSelf: 'Cancel, action: func() begin if fPowerOffState then :DoEvent('Disconnect, nil); else try fEndPoint:Cancel(nil); onexception |evt.ex.comm| do nil; end, debug: "Cancel", _proto: _userproto000 }; AddStepForm(Connected, Cancel); Disconnecting := {declareSelf: 'Disconnecting, debug: "Disconnecting", _proto: _userproto001} ; AddStepForm(Comms FSM, Disconnecting); Disconnect Success := { action: func() begin :DoEvent('UnBind, nil); end, declareSelf: 'DisconnectSuccess, nextState: 'UnBind, debug: "Disconnect Success", _proto: _userproto000 }; AddStepForm(Disconnecting, Disconnect Success); Disconnect Failure := { action: func(error) begin :MNotifyError("Endpoint Disconnect", error); :DoEvent('UnBind, nil); end, declareSelf: 'DisconnectFailure, nextState: 'UnBind, debug: "Disconnect Failure", _proto: _userproto000 }; AddStepForm(Disconnecting, Disconnect Failure); Cancel := {declareSelf: 'Cancel, action: func() begin fAbort := true; try fEndPoint:Cancel(nil); onexception |evt.ex.comm| do nil; end, debug: "Cancel", _proto: _userproto000 }; AddStepForm(Disconnecting, Cancel); UnBind := {declareSelf: 'UnBind, viewBounds: {left: 8, top: 16, right: -8, bottom: 72}, debug: "UnBind", _proto: _userproto001 }; AddStepForm(Comms FSM, UnBind); UnBind := {declareSelf: 'UnBind, action: func() begin try fEndPoint:UnBind(fCompletionSpec); onexception |evt.ex| do :DoEvent('UnBindFailure, [CurrentException()]); end, fCompletionSpec: { async: true, reqTimeout: kNoTimeout, completionScript: func(ep, options, result) begin if result then ep:DoEvent('UnBindFailure, [result]); else ep:DoEvent('UnBindSuccess, nil); end, }, nextState: 'UnBinding, debug: "UnBind", _proto: _userproto000 }; AddStepForm(UnBind, UnBind); Cancel := {declareSelf: 'Cancel, action: func() begin fAbort := true; end, debug: "Cancel", _proto: _userproto000 }; AddStepForm(UnBind, Cancel); UnBinding := {declareSelf: 'UnBinding, debug: "UnBinding", _proto: _userproto001}; AddStepForm(Comms FSM, UnBinding); UnBind Success := { action: func() begin :DoEvent('Dispose, nil); end, declareSelf: 'UnBindSuccess, nextState: 'Dispose, debug: "UnBind Success", _proto: _userproto000 }; AddStepForm(UnBinding, UnBind Success); UnBind Failure := { action: func(exception) begin :MNotifyError("Endpoint UnBind", exception); :DoEvent('Dispose, nil); end, declareSelf: 'UnBindFailure, nextState: 'Dispose, debug: "UnBind Failure", _proto: _userproto000 }; AddStepForm(UnBinding, UnBind Failure); Cancel := {declareSelf: 'Cancel, action: func() begin fAbort := true; try fEndPoint:Cancel(nil); onexception |evt.ex.comm| do nil; end, debug: "Cancel", _proto: _userproto000 }; AddStepForm(UnBinding, Cancel); Dispose := {declareSelf: 'Dispose, viewBounds: {left: 8, top: 16, right: -8, bottom: 72}, debug: "Dispose", _proto: _userproto001 }; AddStepForm(Comms FSM, Dispose); Dispose := { action: func() begin try fEndPoint:Dispose(); onexception |evt.ex| do return :DoEvent('DisposeFailure, [CurrentException()]); :DoEvent('DisposeSuccess, nil); end, declareSelf: 'Dispose, nextState: 'Disposing, debug: "Dispose", _proto: _userproto000 }; AddStepForm(Dispose, Dispose); Cancel := {declareSelf: 'Cancel, action: func() begin fAbort := true; end, debug: "Cancel", _proto: _userproto000 }; AddStepForm(Dispose, Cancel); Disposing := {declareSelf: 'Disposing, debug: "Disposing", _proto: _userproto001}; AddStepForm(Comms FSM, Disposing); Dispose Success := { action: func() begin :DoEvent('CleanUp, nil); end, declareSelf: 'DisposeSuccess, nextState: 'CleanUp, debug: "Dispose Success", _proto: _userproto000 }; AddStepForm(Disposing, Dispose Success); Dispose Failure := { action: func(error) begin :MNotifyError("Endpoint Dispose", error); :DoEvent('CleanUp, nil); end, declareSelf: 'DisposeFailure, nextState: 'CleanUp, debug: "Dispose Failure", _proto: _userproto000 }; AddStepForm(Disposing, Dispose Failure); Cancel := {declareSelf: 'Cancel, action: func() begin fAbort := true; end, debug: "Cancel", _proto: _userproto000 }; AddStepForm(Disposing, Cancel); Clean Up := {declareSelf: 'CleanUp, viewBounds: {left: 8, top: 16, right: -8, bottom: 56}, debug: "Clean Up", _proto: _userproto001 }; AddStepForm(Comms FSM, Clean Up); Clean Up := { action: func() begin if fPowerOffState then begin fPowerOffState := nil; PowerOffResume(kAppSymbol); end; UnRegPowerOff(kAppSymbol); fEndpoint := nil; fAbort := nil; fState := 'Disconnected; fConnectAction := nil; end, declareSelf: 'CleanUp, nextState: 'Genesis, debug: "Clean Up", _proto: _userproto000 }; AddStepForm(Clean Up, Clean Up); // After Script for "Comms FSM" thisView := Comms FSM; call kFSMCleanUpFunc with (thisView); constant |layout_CommsFSM| := Comms FSM; // End of file CommsFSM // Beginning of file Main.t vMain := {title: kAppName, viewBounds: {left: -4, top: 2, right: 224, bottom: 310}, viewFormat: 83951953, FSM: nil, viewQuitScript: // must return the value of inherited:?viewQuitScript(); func() begin FSM:DoEvent('Cancel, nil); FSM:DoEvent('Disconnect, nil); FSM:WaitForTerminal( // this function returns NIL if FSM terminal state reached normally, TRUE if user aborted { statusText: "Please wait...", // message at top of status dialog titleText: "FSM is executing toward terminal state.", // message at bottom of status dialog delayUntilStatusVisible: 2000, // show status slip 2 seconds after entering WaitForTerminal delayUntilAbortVisible: 8000, // show abort button 8 seconds after status dialog opens abortButtonText: "Go Away!", } ); // text inside abort button FSM := FSM:Dispose(); inherited:?viewQuitScript(); // this method is defined internally end, viewSetupFormScript: func() begin // resize to fit on all "small" newtons. constant kMaxWidth := 240; constant kMaxHeight := 336; local b := GetAppParams(); self.viewBounds := RelBounds(b.appAreaLeft, b.appAreaTop, MIN(b.appAreaWidth, kMaxWidth), MIN(b.appAreaHeight, kMaxHeight)); FSM := GetLayout("CommsFSM"):Instantiate(); end, ReorientToScreen: ROM_DefRotateFunc, debug: "vMain", _proto: @157 }; Connect := { buttonClickScript: func() begin FSM:DoEvent('Create, nil); end, text: "Connect", viewBounds: {left: 46, top: 34, right: 114, bottom: 54}, debug: "Connect", _proto: @226 }; AddStepForm(vMain, Connect); Disconnect := { buttonClickScript: func() begin FSM:DoEvent('Disconnect, nil); end, text: "Disconnect", viewBounds: {left: 126, top: 34, right: 194, bottom: 54}, debug: "Disconnect", _proto: @226 }; AddStepForm(vMain, Disconnect); Cancel := { buttonClickScript: func() begin FSM:DoEvent('Cancel, nil); end, text: "Cancel", viewBounds: {left: 86, top: 66, right: 154, bottom: 86}, debug: "Cancel", _proto: @226 }; AddStepForm(vMain, Cancel); vTraceBox := {text: "", viewBounds: {left: 8, top: 108, right: 224, bottom: 180}, viewJustify: 0, viewFont: simpleFont9, debug: "vTraceBox", _proto: @218 }; AddStepForm(vMain, vTraceBox); StepDeclare(vMain, vTraceBox, 'vTraceBox); constant |layout_Main.t| := vMain; // End of file Main.t