def validate(self): # construct an easy dot lookup mechanism from within templates self.nodes = Holder(**self._get_table(Node)) self.boxes = Holder(**self._get_table(Box)) agnostic.collect() # delegate validation to nodes for nodeUid, node in self._get_table(Node).items(): node.validate(self) agnostic.collect()
def run(): show(b"Hello world") while True: agnostic.collect() (stat, tag_type) = rdr.request(rdr.REQIDL) if stat == rdr.OK: (stat, raw_uid) = rdr.anticoll() if stat == rdr.OK: para = b"ID is\n0x%02x%02x%02x%02x" % (raw_uid[0], raw_uid[1], raw_uid[2], raw_uid[3]) show(para)
def ThroughSequence(uid, nextNodeUid, goalBoxUid, sequence, **k): pos = len(sequence) - 1 while pos >= 0: page = sequence[pos] if pos == 0: # first node pageUid = uid # has uid of sequence kwargs = k # inherits all operators etc else: # later nodes pageUid = uid + str( pos - 1) # have uids based on first node uid + position kwargs = {} # don't inherit operators etc ThroughPage(uid=pageUid, page=page, goalBoxUid=goalBoxUid, nextNodeUid=nextNodeUid, **kwargs) nextNodeUid = pageUid pos -= 1 agnostic.collect()
def runBox(boxUid): host = ConsoleHost() agnostic.collect() #TODO CH remove these test lines screen.clear() font.draw_generator(generatorFactory(), plotter) screen.redraw() agnostic.collect() boxUid = str(boxUid) # handle case of passing a number boxEngine = Engine(box=story.lookupBox(boxUid)) boxEngine.registerStory(story) agnostic.collect() while True: agnostic.report_collect() try: tagUid = vault.awaitPresence() try: cardDict = vault.readJson(tagUid=tagUid) if "storyUid" not in cardDict or cardDict["storyUid"] is not loader.storyUid: cardDict = None # existing card data incompatible except Exception as e: if type(e) is KeyboardInterrupt: raise e else: print(e) cardDict = None # couldn't read card for some reason if cardDict is not None: print("JSON Good") card = dictToCard(tagUid, cardDict) else: print("JSON Bad") card = story.createBlankCard(tagUid) agnostic.collect() boxEngine.handleCard(card, host) print("Handled Card") vault.writeJson(cardToDict(card), tagUid=tagUid, unselect=True) print("Written JSON") vault.awaitAbsence() print("Card removed") except AssertionError as ae: print(type(ae).__name__ + str(ae)) except KeyboardInterrupt: break
def displayNode(self, node, host): templateName = node.getRenderedTemplateName(self) templateId = getTemplateId(self.story, node, templateName) # TODO CH consider use of string hash of the template for lazy recompilation useCache = sys.implementation.name == "micropython" generatorFactory = None if useCache: # try to load from cache try: generatorFactory = boilerplate.loadTemplateGeneratorFactory( templateId) except ImportError as e: pass # generatorFactory is still None # lazy - create cache if forced or cache not found if not (useCache) or generatorFactory is None: cacheTemplate(self.story, node, templateName) generatorFactory = boilerplate.loadTemplateGeneratorFactory( templateId) agnostic.collect() generator = generatorFactory(**self.getEngineContext()) agnostic.collect() host.displayGeneratedText(generator) agnostic.collect() # TODO CH Note remove this block, which is not intended for final deployment if sys.implementation.name is not "micropython": maxLineLen = 25 maxLineCount = 8 def generator_to_string(generator): s = "" for chunk in generator: s += chunk return s def check_layout(nodeUid, generator): s = generator_to_string(generator) lines = s.split("\n") if len(lines) > maxLineCount: print() print(s) raise AssertionError("> {} lines in {}".format( maxLineCount, nodeUid)) for line in lines: if len(line) > maxLineLen: print() print(line) raise AssertionError("> {} chars in {}".format( maxLineLen, nodeUid)) check_layout(node.uid, generatorFactory(**self.getEngineContext()))
# screen /dev/ttyUSB0 115200 # from regimes.avatap import runBox; runBox("1") import loader loader.loadAll() import agnostic from faces.font_5x7 import font from st7920 import Screen from mfrc522 import MFRC522 from machine import Pin,SPI from engines import dictToCard, cardToDict from engines import Engine from regimes.console import ConsoleHost from vault import BankVault #TODO CH normalise this story module info into one place (e.g. loader, or via milecastles.loadStory) from stories.corbridge import story agnostic.collect() spi = SPI(1, baudrate=1000000, polarity=0, phase=0) spi.init() agnostic.collect() reader = MFRC522(spi=spi, gpioRst=0, gpioCs=2) agnostic.collect() vault = BankVault(reader) agnostic.collect() screen = Screen(spi=spi, slaveSelectPin=Pin(15)) agnostic.collect() # TODO CH remove this test function (actual plotter is in avatap engine)
def show(msg): screen.clear() font.draw_para(msg, plotter) screen.redraw() collect()
report_import("faces.font_5x7") from faces.font_5x7 import font report_import("vault") report_import("st7920") from st7920 import Screen report_import("machine") from machine import Pin, SPI report_import("mfrc522") from mfrc522 import MFRC522 spi = SPI(1, baudrate=1800000, polarity=0, phase=0) spi.init() collect() rdr = MFRC522(spi=spi, gpioRst=0, gpioCs=2) collect() screen = Screen(spi=spi, slaveSelectPin=Pin(15)) collect() def plotter(x, y): screen.plot(x, y) def show(msg): screen.clear() font.draw_para(msg, plotter)
def evaluateExpression(self, expression): result = eval(expression, self.getEngineContext()) agnostic.collect() return result
def __init__(self, *a, **k): agnostic.collect() for key, val in k.items(): setattr(self, key, val)
def run(self): while True: agnostic.collect() self.handleInput() agnostic.collect()
def gameLoop(self, fuzz=False): agnostic.collect() cardUid = None card = None try: # toast and label finaliser toastRect = None labelRect = None if self.expectStay: labelRect = self.label( awaitReplace ) # draw quickly before clearing rest of screen self.screen.clear() labelRect = self.label(awaitReplace, redraw=False) else: self.screen.clear() if self.resetCard: toastRect = self.toast(b"RESETTING TAG!", redraw=False) else: toastRect = self.toast(b"PLACE TAG\nto read", redraw=False) self.redraw() if self.cardCache or self.resetCard: # block for short period cardUid = self.rfid.awaitPresence(PRESENCE_TIMEOUT) else: cardUid = self.rfid.awaitPresence() # block indefinitely if cardUid is None: # presence timeout was hit if self.cardCache is not None: self.cardCache = None # abandon resume if self.resetCard: self.resetCard = False # abandon reset return None if cardUid in redTags: self.screen.clear() self.redraw() toastRect = self.toast(b"Reset requested") self.expectStay = False self.cardCache = None self.resetCard = True self.rfid.awaitAbsence() return cardUid finally: if toastRect: self.wipeRect(toastRect) if labelRect: self.wipeRect(labelRect) try: # unselect finaliser self.rfid.selectTag(cardUid) if self.resetCard and not (cardUid in redTags): self.resetCard = False card = self.story.createBlankCard(cardUid) self.rfid.writeCard(card=card, unselect=True) toastRect = self.toast(b"Reset complete") self.rfid.awaitAbsence() self.wipeRect(toastRect) return cardUid elif self.cardCache is not None: if cardUid == self.cardCache.uid: card = self.cardCache # resume avoiding any read else: pass # do not load from cache - wrong card self.cardCache = None # discard cached data from previous cycle (implicitly after resumeMs) if card is None: try: labelRect = self.label(b"KEEP IN PLACE, loading..") agnostic.collect() card = self.rfid.readCard(cardUid=cardUid, unselect=False) if card.storyUid != self.story.uid or card.storyVersion != self.story.version: raise CardJsonIncompatibleError( "Wrong story or version") except CardReadIncompleteError: return None # exit the loop altogether except (CardBankMissingError, CardJsonInvalidError, CardJsonIncompatibleError, AssertionError): card = self.story.createBlankCard( cardUid ) # overwrite the card, read was successful but content flawed try: # label finaliser labelRect = self.label( b"KEEP IN PLACE, saving..." ) # TODO CH calculate location to just wipe and draw 'saving.' over 'loading' origNodeUid = card.nodeUid agnostic.collect() nextNode = self.engine.handleCard(card, self) # will next page also be at this box? if issubclass( type(nextNode), GoalPage) and nextNode.goalBoxUid == self.box.uid: self.expectStay = True # goalpage at same box elif nextNode.uid != origNodeUid: self.expectStay = True # remote GoalPage or NodeFork unvisited else: self.expectStay = False # remote GoalPage or NodeFork now visited try: agnostic.collect() self.rfid.writeCard(card=card, unselect=False) self.cardCache = card except: print("Error; discarding write. One of...") print("Card identity not the intended card to be written") print("Card removed before write complete") finally: self.wipeRect(labelRect) # TODO try this to avoid error counting in awaitAbsence (meaning two presence cycles needed to detect) # cardVault.reader.reset() finally: try: labelRect = self.label( awaitLift if self.expectStay else awaitLeave, redraw=False) self.redraw( ) # TODO redraw fully as workaround for draw alignment bug which seems only to affect this message self.rfid.unselectTag() if not fuzz: # if fuzzing, don't wait for tag lift self.rfid.awaitAbsence() print("CARD REMOVED") finally: self.wipeRect(labelRect) return cardUid