From 9d1598938dbf5ff4b33b9fdcc98ba967385d2297 Mon Sep 17 00:00:00 2001 From: Bhaskar Mookerji Date: Fri, 19 Jun 2015 13:15:13 -0700 Subject: [PATCH 1/2] Step1: Fix Piksi's lack of social networking features. Step3: .... /cc @fnoble @mfine @henryhallam --- c/include/libsbp/logging.h | 10 +++++ python/sbp/logging.py | 70 +++++++++++++++++++++++++++++ python/tests/sbp/test_table.py | 2 +- spec/yaml/swiftnav/sbp/logging.yaml | 11 +++++ 4 files changed, 92 insertions(+), 1 deletion(-) diff --git a/c/include/libsbp/logging.h b/c/include/libsbp/logging.h index 7744975436..da10739769 100644 --- a/c/include/libsbp/logging.h +++ b/c/include/libsbp/logging.h @@ -47,6 +47,16 @@ typedef struct __attribute__((packed)) { #define SBP_MSG_DEBUG_VAR 0x0011 +/** Tweet + * +* All the news fit to tweet. + */ +#define SBP_MSG_TWEET 0x0012 +typedef struct __attribute__((packed)) { + char tweet[140]; /**< Human-readable string */ +} msg_tweet_t; + + /** \} */ #endif /* LIBSBP_LOGGING_MESSAGES_H */ \ No newline at end of file diff --git a/python/sbp/logging.py b/python/sbp/logging.py index 7f61e0cd82..c535a48437 100755 --- a/python/sbp/logging.py +++ b/python/sbp/logging.py @@ -126,8 +126,78 @@ def __repr__(self): return fmt_repr(self) +SBP_MSG_TWEET = 0x0012 +class MsgTweet(SBP): + """SBP class for message MSG_TWEET (0x0012). + + You can have MSG_TWEET inherent its fields directly + from an inherited SBP object, or construct it inline using a dict + of its fields. + + + All the news fit to tweet. + + Parameters + ---------- + sbp : SBP + SBP parent object to inherit from. + tweet : string + Human-readable string + sender : int + Optional sender ID, defaults to 0 + + """ + _parser = Struct("MsgTweet", + String('tweet', 140),) + + def __init__(self, sbp=None, **kwargs): + if sbp: + self.__dict__.update(sbp.__dict__) + self.from_binary(sbp.payload) + else: + super( MsgTweet, self).__init__() + self.msg_type = SBP_MSG_TWEET + self.sender = kwargs.pop('sender', 0) + self.tweet = kwargs.pop('tweet') + + def __repr__(self): + return fmt_repr(self) + + def from_binary(self, d): + """Given a binary payload d, update the appropriate payload fields of + the message. + + """ + p = MsgTweet._parser.parse(d) + self.__dict__.update(dict(p.viewitems())) + + def to_binary(self): + """Produce a framed/packed SBP message. + + """ + c = containerize(exclude_fields(self)) + self.payload = MsgTweet._parser.build(c) + return self.pack() + + @staticmethod + def from_json(s): + """Given a JSON-encoded string s, build a message object. + + """ + d = json.loads(s) + sbp = SBP.from_json_dict(d) + return MsgTweet(sbp) + + def to_json_dict(self): + self.to_binary() + d = super( MsgTweet, self).to_json_dict() + j = walk_json_dict(exclude_fields(self)) + d.update(j) + return d + msg_classes = { 0x0010: MsgPrint, 0x0011: MsgDebugVar, + 0x0012: MsgTweet, } \ No newline at end of file diff --git a/python/tests/sbp/test_table.py b/python/tests/sbp/test_table.py index 1cbfbe8d99..5b7e9a0ee2 100644 --- a/python/tests/sbp/test_table.py +++ b/python/tests/sbp/test_table.py @@ -34,7 +34,7 @@ def test_table_count(): Test number of available messages to deserialize. """ - number_of_messages = 53 + number_of_messages = 54 assert len(_SBP_TABLE) == number_of_messages def test_table_unqiue_count(): diff --git a/spec/yaml/swiftnav/sbp/logging.yaml b/spec/yaml/swiftnav/sbp/logging.yaml index dab426a8bf..947bc7abf4 100644 --- a/spec/yaml/swiftnav/sbp/logging.yaml +++ b/spec/yaml/swiftnav/sbp/logging.yaml @@ -37,3 +37,14 @@ definitions: desc: | This is an unused legacy message for tracing variable values within the device firmware and streaming those back to the host. + + - MSG_TWEET: + id: 0x0012 + public: False + short_desc: Tweet + desc: All the news fit to tweet. + fields: + - tweet: + type: string + size: 140 + desc: Human-readable string From 1e80e29225805f633e8a50ab9c94e49746290160 Mon Sep 17 00:00:00 2001 From: Fergus Noble Date: Fri, 19 Jun 2015 13:36:05 -0700 Subject: [PATCH 2/2] Example using the TWEET message --- python/sbp/client/examples/tweet.py | 64 +++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 python/sbp/client/examples/tweet.py diff --git a/python/sbp/client/examples/tweet.py b/python/sbp/client/examples/tweet.py new file mode 100644 index 0000000000..4a00854b15 --- /dev/null +++ b/python/sbp/client/examples/tweet.py @@ -0,0 +1,64 @@ +# Copyright (C) 2015 Swift Navigation Inc. +# Contact: Fergus Noble +# +# This source is subject to the license found in the file 'LICENSE' which must +# be be distributed together with this source. All other rights reserved. +# +# THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, +# EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + +""" +the :mod:`sbp.client.examples.tweet` module contains a basic example of +reading SBP messages from a serial port, decoding TWEET messages and pushing +them to the twitter API. +""" + +from sbp.client.drivers.pyserial_driver import PySerialDriver +from sbp.client.handler import Handler +from sbp.logging import SBP_MSG_TWEET, MsgTweet + +import time +import twitter + +twit = None + +def tweet_callback(msg): + # This function is called every time we receive a TWEET message + if twit is not None: + twit.statuses.update(status=MsgTweet(msg).tweet) + +def main(): + + import argparse + parser = argparse.ArgumentParser(description="Swift Navigation Tweetxample.") + parser.add_argument("TOKEN") + parser.add_argument("TOKEN_KEY") + parser.add_argument("CON_SEC") + parser.add_argument("CON_SEC_KEY") + parser.add_argument("-p", "--port", + default=['/dev/ttyUSB0'], nargs=1, + help="specify the serial port to use.") + args = parser.parse_args() + + my_auth = twitter.OAuth(args.TOKEN, args.TOKEN_KEY, + args.CON_SEC, args.CON_SEC_KEY) + twit = twitter.Twitter(auth=my_auth) + + # Open a connection to Piksi using the default baud rate (1Mbaud) + with PySerialDriver(args.port[0], baud=1000000) as driver: + # Create a handler to connect our Piksi driver to our callbacks + with Handler(driver.read, driver.write, verbose=True) as handler: + # Add a callback for BASELINE_NED messages + handler.add_callback(baseline_callback, msg_type=SBP_MSG_BASELINE_NED) + + # Sleep until the user presses Ctrl-C + try: + while True: + time.sleep(0.1) + except KeyboardInterrupt: + pass + +if __name__ == "__main__": + main() +