def test_copy_constant_statement(parser): """Make sure we can copy constant values.""" parser.parse_file(get_path(u'basic_copy_constant.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) sg.load_constants() output1 = log.create_walker(DataStreamSelector.FromString('output 1')) sim = SensorGraphSimulator(sg) sim.stop_condition('run_time 10 seconds') sim.run() assert output1.count() == 1 assert output1.pop().value == 15 sim.step(DataStream.FromString('input 1'), 10) assert output1.count() == 1 assert output1.pop().value == 0x10
def main(): """Main entry point for iotile-sgcompile.""" arg_parser = build_args() args = arg_parser.parse_args() model = DeviceModel() parser = SensorGraphFileParser() parser.parse_file(args.sensor_graph) if args.format == u'ast': write_output(parser.dump_tree(), True, args.output) sys.exit(0) parser.compile(model) if not args.disable_optimizer: opt = SensorGraphOptimizer() opt.optimize(parser.sensor_graph, model=model) if args.format == u'nodes': output = u'\n'.join(parser.sensor_graph.dump_nodes()) + u'\n' write_output(output, True, args.output) else: if args.format not in KNOWN_FORMATS: print("Unknown output format: {}".format(args.format)) sys.exit(1) output_format = KNOWN_FORMATS[args.format] output = output_format.format(parser.sensor_graph) write_output(output, output_format.text, args.output)
def test_copy_statement(parser): """Make sure we can copy data using copy.""" parser.parse_file(get_path(u'basic_copy.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) sg.load_constants() output1 = log.create_walker(DataStreamSelector.FromString('output 1')) output2 = log.create_walker(DataStreamSelector.FromString('output 2')) output3 = log.create_walker(DataStreamSelector.FromString('output 3')) sim = SensorGraphSimulator(sg) sim.stop_condition('run_time 60 seconds') sim.run() assert output1.count() == 1 assert output2.count() == 1 assert output3.count() == 1 val1 = output1.pop() val2 = output2.pop() val3 = output3.pop() assert val1.value == 0 assert val2.value == 60 assert val3.value == 1
def test_stream_allocation(): """Make sure we can allocate DataStreams.""" model = DeviceModel() log = SensorLog(model=model) sg = SensorGraph(log, model=model) # TODO Finish this function alloc = StreamAllocator(sg, model=model) stream1 = alloc.allocate_stream(DataStream.ConstantType) assert len(sg.nodes) == 0 stream2 = alloc.attach_stream(stream1) assert len(sg.nodes) == 0 stream3 = alloc.attach_stream(stream1) assert len(sg.nodes) == 0 stream4 = alloc.attach_stream(stream1) assert len(sg.nodes) == 0 stream5 = alloc.attach_stream(stream1) assert len(sg.nodes) == 1 assert stream1 == stream2 assert stream2 == stream3 assert stream4 == stream1 assert stream5 != stream1
def test_on_block_dual(parser): """Make sure on with two conditions works.""" parser.parse_file(get_path(u'basic_on_dual.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) sg.load_constants() counter1 = log.create_walker(DataStreamSelector.FromString('counter 1')) sim = SensorGraphSimulator(sg) sim.step(DataStream.FromString('input 1'), 5) assert counter1.count() == 0 sim.step(DataStream.FromString('input 2'), 1) for _i in range(0, 10): sim.step(DataStream.FromString('input 1'), 5) assert counter1.count() == 11 sim.step(DataStream.FromString('input 2'), 0) for _i in range(0, 10): sim.step(DataStream.FromString('input 1'), 5) assert counter1.count() == 11
def test_on_block(parser): """Make sure on count(stream), on value(stream) and on stream work.""" parser.parse_file(get_path(u'basic_on.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) sg.load_constants() counter1 = log.create_walker(DataStreamSelector.FromString('counter 1')) counter2 = log.create_walker(DataStreamSelector.FromString('counter 2')) counter3 = log.create_walker(DataStreamSelector.FromString('counter 3')) sim = SensorGraphSimulator(sg) sim.step(DataStream.FromString('input 1'), 8) assert counter1.count() == 0 assert counter2.count() == 0 assert counter3.count() == 0 for i in range(0, 10): sim.step(DataStream.FromString('input 1'), 5) assert counter1.count() == 10 assert counter2.count() == 5 assert counter3.count() == 5
def test_every_block_compilation(parser): """Make sure we can compile a simple every block.""" parser.parse_file(get_path(u'basic_every_1min.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) assert len(sg.nodes) == 7 sg.load_constants() # Now make sure it produces the right output counter15 = log.create_walker(DataStreamSelector.FromString('counter 15')) counter16 = log.create_walker(DataStreamSelector.FromString('counter 16')) sim = SensorGraphSimulator(sg) sim.stop_condition('run_time 120 seconds') sim.run() assert counter15.count() == 2 assert counter16.count() == 2
def test_when_block_on_event(parser): """Make sure on connect and on disconnect work.""" parser.parse_file(get_path(u'basic_when_on.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) sg.load_constants() sim = SensorGraphSimulator(sg) # We should only get a reading in unbuffered 1 on connect and unbuffered 2 on disconnect with pytest.raises(StreamEmptyError): log.inspect_last(DataStream.FromString('unbuffered 2')) sim.step(DataStream.FromString('system input 1025'), 8) assert log.inspect_last(DataStream.FromString('unbuffered 1')).value == 0 with pytest.raises(StreamEmptyError): log.inspect_last(DataStream.FromString('unbuffered 2')) sim.step(DataStream.FromString('system input 1026'), 8) assert log.inspect_last(DataStream.FromString('unbuffered 2')).value == 0
def test_when_block_clock(parser): """Make sure we can compile when blocks (without identifiers).""" parser.parse_file(get_path(u'basic_when.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) sg.load_constants() assert sg.get_tick('fast') == 1 # Now make sure it produces the right output counter15 = log.create_walker(DataStreamSelector.FromString('counter 15')) sim = SensorGraphSimulator(sg) sim.stop_condition('run_time 60 seconds') sim.run() assert counter15.count() == 0 sim.step(DataStream.FromString('system input 1025'), 8) assert counter15.count() == 1 counter15.skip_all() sim.run() assert counter15.count() == 60 counter15.skip_all() sim.step(DataStream.FromString('system input 1026'), 8) sim.run() assert counter15.count() == 0
def test_every_block_splitting(parser): """Make sure we can split nodes in an every block.""" parser.parse_file(get_path(u'basic_every_split.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) assert len(sg.nodes) == 10 # Now make sure it produces the right output counter15 = log.create_walker(DataStreamSelector.FromString('counter 15')) counter16 = log.create_walker(DataStreamSelector.FromString('counter 16')) counter17 = log.create_walker(DataStreamSelector.FromString('counter 16')) counter18 = log.create_walker(DataStreamSelector.FromString('counter 16')) sg.load_constants() sim = SensorGraphSimulator(sg) sim.stop_condition('run_time 120 seconds') sim.run() sg.load_constants() print([str(x) for x in log._last_values.keys()]) assert counter15.count() == 2 assert counter16.count() == 2 assert counter17.count() == 2 assert counter18.count() == 2
def test_every_block_with_buffering(parser): """Make sure we can compile and simulate an every block with buffered data.""" parser.parse_file(get_path(u'basic_output.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) assert len(sg.nodes) == 7 sg.load_constants() # Now make sure it produces the right output output1 = log.create_walker(DataStreamSelector.FromString('output 1')) buffered1 = log.create_walker(DataStreamSelector.FromString('buffered 1')) sim = SensorGraphSimulator(sg) sim.stop_condition('run_time 120 seconds') sim.run() assert output1.count() == 12 assert buffered1.count() == 12
def test_copy_count_statement(parser): """Make sure we can copy data count using copy count.""" parser.parse_file(get_path(u'count.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) sg.load_constants() output = log.create_walker(DataStreamSelector.FromString('output 1')) sim = SensorGraphSimulator(sg) sim.stop_condition('run_time 3 seconds') sim.step(user_connected, 8) # Simulates a connected user sim.run() print(output) assert output.count() == 1 print(output)
def test_subtract_nonconstant(parser): """Make we we raise an error if you subtract a nonconstant stream.""" parser.parse_file(get_path(u'basic_subtract_error.sgf')) model = DeviceModel() with pytest.raises(SensorGraphSemanticError): parser.compile(model=model)
def basic_sg(): model = DeviceModel() log = SensorLog(model=model) sg = SensorGraph(log, model=model) sg.add_node('(system input 2 always) => unbuffered 1 using copy_all_a') return sg
def compile_sg(name): """Compile a sensor graph.""" parser = SensorGraphFileParser() model = DeviceModel() parser.parse_file(get_path(name)) parser.compile(model=model) return parser.sensor_graph
def complex_gate_opt(): """Optimize the complex_gate sensor_graph.""" model = DeviceModel() optimizer = SensorGraphOptimizer() raw_sg = compile_sg('complex_gates.sgf') optimizer.optimize(raw_sg, model=model) return raw_sg
def usertick_gate_opt(): """Optimize the user tick sensor graph.""" model = DeviceModel() optimizer = SensorGraphOptimizer() raw_sg = compile_sg('user_tick.sgf') optimizer.optimize(raw_sg, model=model) return raw_sg
def usertick_sg(): model = DeviceModel() log = SensorLog(model=model) sg = SensorGraph(log, model=model) sg.add_node('(system input 3 always) => counter 1 using copy_latest_a') sg.add_config(SlotIdentifier.FromString('controller'), config_fast_tick_secs, 'uint32_t', 2) return sg
def streamer_types(): """Sensorgraph with lots of varieties of streamers.""" model = DeviceModel() optimizer = SensorGraphOptimizer() raw_sg = compile_sg('streamers.sgf') optimizer.optimize(raw_sg, model=model) return raw_sg
def test_usertick(): """Make sure we properly can set the user tick input.""" model = DeviceModel() log = SensorLog(model=model) sg = SensorGraph(log, model=model) assert sg.get_tick('fast') == 0 sg.add_config(SlotIdentifier.FromString('controller'), config_fast_tick_secs, 'uint32_t', 1) assert sg.get_tick('fast') == 1
def test_basic_sensorgraph(): """Make sure we can parse, load and run a basic sensor graph.""" model = DeviceModel() log = SensorLog(model=model) sg = SensorGraph(log, model=model) sg.add_node('(input 1 always && input 2 when count >= 1) => unbuffered 1 using copy_all_a') sg.process_input(DataStream.FromString('input 1'), IOTileReading(0, 1, 1), rpc_executor=None) sg.process_input(DataStream.FromString('input 2'), IOTileReading(0, 1, 1), rpc_executor=None) assert sg.sensor_log.inspect_last(DataStream.FromString('unbuffered 1')).value == 1
def callrpc_sg(): model = DeviceModel() log = SensorLog(model=model) sg = SensorGraph(log, model=model) sg.add_node( '(system input 2 always && constant 1 always) => unbuffered 2 using call_rpc' ) log.push(DataStream.FromString('constant 1'), IOTileReading(0, 0, 0x000a8000)) return sg
def tick2_sg(): """A sensorgrah that listens to tick1.""" model = DeviceModel() log = SensorLog(model=model) sg = SensorGraph(log, model=model) sg.add_node('(system input 6 always) => counter 1 using copy_latest_a') sg.add_config(SlotIdentifier.FromString('controller'), config_tick2_secs, 'uint32_t', 2) return sg
def test_root_buffering(parser): """Make sure that nodes with two inputs where only one of the inputs is a root node gets an unbuffered node in between. Furthermore, check that after topographic sorting, the root nodes are all at the top.""" parser.parse_file(get_path(u'basic_root_buffering.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) assert len(sg.nodes) == 21 #This check is to ensure that all root (input) nodes at the beginning after sorting. root_node_section_passed = False for node in sg.nodes: if not root_node_section_passed: if 'input' not in str(node): root_node_section_passed = True else: assert 'input' not in str(node) # Now make sure it produces the right output output11 = log.create_walker(DataStreamSelector.FromString('output 11')) output12 = log.create_walker(DataStreamSelector.FromString('output 12')) output13 = log.create_walker(DataStreamSelector.FromString('output 13')) output14 = log.create_walker(DataStreamSelector.FromString('output 14')) output15 = log.create_walker(DataStreamSelector.FromString('output 15')) sg.load_constants() sim = SensorGraphSimulator(sg) sim.stop_condition('run_time 20 minutes') sim.stimulus("1 minute: input 1 = 1") sim.stimulus("1 minute: input 2 = 1") sim.stimulus("11 minute: input 1 = 2") sim.run() sg.load_constants() print([str(x) for x in log._last_values.keys()]) assert output11.count() == 2 assert output12.count() == 2 assert output13.count() == 2 assert output14.count() == 2 assert output15.count() == 1
def test_meta_statement(parser): """Make sure we properly store metadata.""" parser.parse_file(get_path(u'basic_meta_file.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph assert sg.metadata_database['name'] == 'NFC300' assert sg.metadata_database['version'] == '1.0.0' assert sg.metadata_database['cloud_name'] == 'nfc300-1-0-0' assert sg.metadata_database['app_tag'] == 1024
def test_config_block_binary(parser): """Make sure config blocks can parse binary config variables.""" parser.parse_file(get_path(u'binary_config.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph assert len(sg.config_database) == 2 valtype, val = sg.get_config(SlotIdentifier.FromString('slot 1'), 0x2000) assert valtype == u'binary' assert isinstance(val, bytes)
def test_streamers(parser): """Make sure we can compile streamer statements.""" parser.parse_file(get_path(u'basic_streamer.sgf')) model = DeviceModel() parser.compile(model=model) streamers = parser.sensor_graph.streamers assert len(streamers) == 3 assert streamers[0].dest == SlotIdentifier.FromString('controller') assert streamers[1].dest == SlotIdentifier.FromString('slot 1') assert streamers[1].with_other == 0 assert streamers[2].dest == SlotIdentifier.FromString('controller') assert streamers[2].report_type == 'broadcast'
def test_iteration(): """Make sure we can iterate over the graph.""" model = DeviceModel() log = SensorLog(model=model) sg = SensorGraph(log, model=model) sg.add_node( '(input 1 always && input 2 when count >= 1) => unbuffered 1 using copy_all_a' ) sg.add_node( '(input 1 always && input 3 when count >= 1) => unbuffered 2 using copy_all_a' ) sg.add_node( '(unbuffered 2 always && unbuffered 1 always) => unbuffered 3 using copy_all_a' ) sg.add_node('(unbuffered 1 always) => unbuffered 3 using copy_all_a') iterator = sg.iterate_bfs() node1, in1, out1 = next(iterator) assert str(node1.stream) == u'unbuffered 1' assert len(in1) == 0 assert len(out1) == 2 assert str(out1[0].stream) == u'unbuffered 3' assert str(out1[1].stream) == u'unbuffered 3' node1, in1, out1 = next(iterator) assert str(node1.stream) == u'unbuffered 2' assert len(in1) == 0 assert len(out1) == 1 assert str(out1[0].stream) == u'unbuffered 3' node1, in1, out1 = next(iterator) assert str(node1.stream) == u'unbuffered 3' assert len(in1) == 2 assert len(out1) == 0 assert str(in1[0].stream) == u'unbuffered 2' assert str(in1[1].stream) == u'unbuffered 1' node1, in1, out1 = next(iterator) assert str(node1.stream) == u'unbuffered 3' assert len(in1) == 1 assert len(out1) == 0 assert str(in1[0].stream) == u'unbuffered 1'
def main(): arg_parser = build_args() args = arg_parser.parse_args() model = DeviceModel() parser = SensorGraphFileParser() parser.parse_file(args.sensor_graph) outfile = sys.stdout if args.output is not None: outfile = open(args.output, "wb") if args.format == u'ast': outfile.write(parser.dump_tree().encode()) outfile.close() sys.exit(0) parser.compile(model) if not args.disable_optimizer: opt = SensorGraphOptimizer() opt.optimize(parser.sensor_graph, model=model) if args.format == u'nodes': for node in parser.sensor_graph.dump_nodes(): outfile.write((node + u'\n').encode()) else: if args.format not in known_formats: print("Unknown output format: {}".format(args.format)) outfile.close() sys.exit(1) output = known_formats[args.format](parser.sensor_graph) if args.format in (u'snippet', u'ascii', u'config'): outfile.write(output.encode()) else: outfile.write(output) outfile.close()
def test_config_block(parser): """Make sure config blocks and statement are parsed.""" parser.parse_file(get_path(u'basic_config.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph assert len(sg.config_database) == 5 assert sg.get_config(SlotIdentifier.FromString('controller'), 0x2000) == (u'uint32_t', 5) assert sg.get_config(SlotIdentifier.FromString('slot 1'), 0x5000) == (u'uint8_t', 10) assert sg.get_config(SlotIdentifier.FromString('slot 2'), 0x5100) == (u'int8_t', -10) assert sg.get_config(SlotIdentifier.FromString('slot 3'), 0x5200) == (u'uint8_t[]', u'[10,20,30,40]') assert sg.get_config(SlotIdentifier.FromString('slot 4'), 0x5300) == (u'string', u'test')