PMU Agenda Concurrent Model Real Time Model
Environment (1) public createEvents: () ==> () createEvents () == ( if len inlines > 0 then ( dcl curtime : nat := NewWorld`timerRef.GetTime(), done : bool := false; while not done do def mk_(eventtype, theEvent, timestamp) = hd inlines in if timestamp <= curtime then ( cases eventtype: 1 -> ( def mk_(cpr, eventid, datatype, devicedata) = theEvent in for all device in set elems devices do if (device.getCprNr() = cpr and device.getDeviceType() = datatype) then ( device.poll(eventid, datatype, devicedata, timestamp) ), 2 -> ( def mk_(cpr, eventid) = theEvent in for all pmu in set elems pmus do if (pmu.getPMUId() = cpr) then ( pmu.proximity() ), others -> Printer`Out("Env: Something bad happened... crap...") end; inlines := tl inlines; done := len inlines = 0; ) else done := true ) else busy := false);
Environment (2) [mk_(1, mk_( , 1, 1, [mk_(1,0), mk_(1,1), mk_(1,2), mk_(2,3), mk_(3,4)]), 10), mk_(2, mk_(2, ), 20)] EventData = EventType * Event * TimeStamp Event = Data | ProximityEvent Data = CprNr * EventId * DataType * seq of DeviceData DeviceData = nat * TimeStamp ProximityEvent = EventId * CprNr EventType (Data poll event) Event (Data) TimeStamp EventType (Proximity event) Event (Proximity) TimeStamp
MedicalDevice Contains the data the PMU is collecting. The environment instigates the polling on the correct medicaldevice based on the CPR nr and device type. public poll: EventId * DataType * seq of DeviceData * TimeStamp ==> () poll(evid, dtype, devicedata, ts) == ( pmuref.collectDeviceData(evid, dtype, devicedata, ts) );
PMU public collectDeviceData : EventId * DataType * seq of DeviceData * TimeStamp ==> () collectDeviceData(evid, datatype, devicedata, ts) == ( if datatype = 3 then (mdDataPrio3 := mdDataPrio3 ^ [mk_(evid, datatype, devicedata, ts)];) else if datatype = 2 then (mdDataPrio2 := mdDataPrio2 ^ [mk_(evid, datatype, devicedata, ts)];) else if datatype = 1 then (mdDataPrio1 := mdDataPrio1 ^ [mk_(evid, datatype, devicedata, ts)];) ); processData: () ==> () processData() == ( ( for all analyzerId in set dom analyzer do if(analyzerId = HEARTRATE) then def mk_(evid, datatype, devicedata, pt) = getData(mdDataPrio3) in ( while (len mdDataPrio3 > 0) do (analyzer(analyzerId).addData(evid, datatype, devicedata, pt)) ) else if(analyzerId = TAKEMEDICIN) then def mk_(evid, datatype, devicedata, pt) = getData(mdDataPrio2) in ( while (len mdDataPrio3 = 0 and len mdDataPrio2 > 0) do (analyzer(analyzerId).addData(evid, datatype, devicedata, pt)) ) else if(analyzerId = WEIGHT) then def mk_(evid, datatype, devicedata, pt) = getData(mdDataPrio1) in ( while (len mdDataPrio3 = 0 and len mdDataPrio2 = 0 and len mdDataPrio1 > 0) do (analyzer(analyzerId).addData(evid, datatype, devicedata, pt)) ) );
Analyzer public doStuff: () ==> () doStuff() == ( (dcl curData : Data := hd dataBuffer; def mk_(evid, datatype, devicedata, pt) = curData in ( if hasBattery then batMonitor.drain(20); for all value in set elems devicedata ( def mk_(val, timestamp) = value in ( oldValue := curValue; curValue : = val; if(curValue - oldValue > 5) transmitter.send(evid, HEART_RATE_SPIKE, devicedata, NewWorld`timerRef.GetTime()); ); ): dataBuffer := tl dataBuffer; if len dataBuffer = 0 then busy:= false; ) );
Transmitter Sorts messages by priority and transmits the highest priority first. sortByPriority: TransmitData * seq of TransmitData ==> seq of TransmitData sortByPriority(val, sorted) == ( cases true: (len sorted = 0) -> return [val], (val.#2 return [val] ^ sorted, others -> return [hd sorted] ^ sortByPriority(val, tl sorted) end ); private sendMessage: () ==> () sendMessage() == ( if busy then ( dcl msg : TransmitData := hd prioritizedBuffer; prioritizedBuffer := tl prioritizedBuffer; Environment'handleEvent(msg, NewWorld`timerRef.GetTime()); battery.drain(drainVolume(msg.#2)); busy:=len buffer > 0 ) );
BatteryMonitor Symbolizes the battery and the drain on this from different operations. If there’s no battery left, processes are halted in the drain call. public drain: nat ==> () drain(drainVolume) == batteryLife := batteryLife - drainVolume; sync mutex(drain); mutex(drain, getBatteryLife, recharge); per drain => batteryLife > 0
Real Time Overview
Real Time MedicalDevice The analysis algorithm has a cycles added due to the computation. async public poll: EventId * DataType * seq of DeviceData * TimeStamp ==> () poll(evid, dtype, devicedata, ts) == ( pmuref.collectDeviceData(evid, dtype, devicedata, ts) );
Real Time PMU Thread becomes periodic a number of cycles is added to processData. collectDeviceData has a duration added due to communication initialization. thread periodic(500, 0, 0, 0) (processData) processData: () ==> () processData() == cycles(100) ( … ); public collectDeviceData : EventId * DataType * seq of DeviceData * TimeStamp ==> () collectDeviceData(evid, datatype, devicedata, ts) == duration(20) ( … );
Real Time Analyzer thread periodic(500, 100, 0, 0) (doStuff) public doStuff: () ==> () doStuff() == Cycles(5000) ( … );
Real Time Transmitter async public transmit: TransmitData ==> () transmit(data) == ( buffer := sortByPriority(data, buffer); busy:= true; ); thread periodic(500, 10, 0, 0) (sendMessage) private sendMessage: () ==> () sendMessage() == duration(50) ( … );