{ "info": { "author": "Amos Latteier", "author_email": "amos@latteier.com", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: MIT License", "Operating System :: MacOS", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX", "Topic :: Communications :: Telephony" ], "description": "SMS\n===\n\nThe sms package provides sms capabilities for enfora gsm modems, and\nprobably others.\n\nThe sms package provides Modem and Message classes for sending and\nreceiving sms message.\n\nThe sms.server module provides two servers that allow you to dispatch\nincoming sms messages. The sms.echo module is an example that works\nwith the sms.server.subprocess_server.\n\nUsage\n-----\n\nCreate a modem object passing it the serial device ID. On windows this\nwould be something like 'COM1'. The example below is for mac and\nlinux:\n\n >>> import sms\n >>> m = sms.Modem('/dev/ttyS0')\n\nYou can have use several modem objects concurrently if you have more\nthan one modem attached to different serial ports.\n\nFor the purposes of this test we're going to replace the real serial\nconnection on the modem with a dummy one so that the test doesn't\nactually send sms messages.\n\n >>> m.conn = DummyConnection()\n\nThe dummy connection will simply keep a list of AT commands sent\nrather than actually sending them to a modem.\n\nTo send a sms message call the send method, passing a phone number\nstring and a message string.\n\n >>> m.send('14161234567', 'This is a message')\n\nLet's see what AT commands were sent.\n\n >>> m.conn.sent()\n 'AT+CMGS=\"14161234567\"\\r\\nThis is a message\\x1a'\n\nThe AT+CMGS command was send, followed by the sms message terminated\nwith ctrl-z.\n\nLet's simulate an error in sending, by hardcoding the connection to\nreturn an error string.\n\n >>> m.conn.response = ['ERROR']\n\nNow let's try to send a message.\n\n >>> m.send('14161234567', 'This is a message')\n Traceback (most recent call last):\n ...\n ModemError: ['ERROR']\n\nA ModemError is raised with the error message.\n\nLet's restore the normal connection response.\n\n >>> m.conn.response = []\n\nYou can receive sms messages with the messages() method. It retuns a\nlist of all messages that have been received.\n\n >>> m.messages()\n []\n\nSo far no messages have been received. Let's see how the modem asks\nfor messages.\n\n >>> m.conn.reset()\n >>> m.messages()\n []\n >>> m.conn.sent()\n 'AT+CMGL=\"ALL\"\\r\\n'\n\nThe AT+CMGL message tells the modem to list stored messages. Let's\nsimulate a typical response to this command.\n\n >>> m.conn.response = ['\\r\\n', '+CMGL: 1,\"REC UNREAD\",\"+16476186676\",,\"08/07/11,11:02:11+00\"\\r\\n', 'Activation code 63966 Go 2 www.ipipi.com and signin with your username and pwd, enter 63966 to activate your mobile/account\\r\\n', '\\r\\n', '\\r\\n', 'Welcome 2 ipipi.com\\r\\n', 'OK\\r\\n']\n\nNow we let's try again.\n\n >>> msgs = m.messages()\n >>> msgs\n []\n\nMessage objects have a couple attributes: number, date, and text.\n\n >>> msgs[0].number\n '+16476186676'\n\n >>> msgs[0].date\n datetime.datetime(2008, 7, 11, 11, 2, 11)\n\n >>> msgs[0].text\n 'Activation code 63966 Go 2 www.ipipi.com and signin with your username and pwd, enter 63966 to activate your mobile/account\\n\\nWelcome 2 ipipi.com'\n\nLet's do a more complex example to make sure that we can deal with\ndifferent types of messages.\n\n >>> m.conn.response = ['\\r\\n', '+CMGL: 1,\"REC READ\",\"+16476186676\",,\"08/07/11,11:02:11+00\"\\r\\n', 'Activation code 63966 Go 2 www.ipipi.com and signin with your username and pwd, enter 63966 to activate your mobile/account\\r\\n', '\\r\\n', '\\r\\n', 'Welcome 2 ipipi.com\\r\\n', '+CMGL: 2,\"STO UNSENT\",\"14166243508\",,\\r\\n', 'Out over the fields,\\r\\n', '\\n', 'attached to nothing,\\r\\n', '\\n', 'a skylark sings\\r\\n', '\\r\\n', '+CMGL: 3,\"REC READ\",\"+14161234567\",\"Example Name\",\"08/07/11,13:02:11+00\"\\r\\n', 'Test message\\r\\n','OK\\r\\n']\n\n >>> msgs = m.messages()\n >>> len(msgs)\n 3\n >>> msgs[0].number\n '+16476186676'\n >>> msgs[0].date\n datetime.datetime(2008, 7, 11, 11, 2, 11)\n >>> msgs[0].text\n 'Activation code 63966 Go 2 www.ipipi.com and signin with your username and pwd, enter 63966 to activate your mobile/account\\n\\nWelcome 2 ipipi.com'\n >>> msgs[2].number\n '+14161234567'\n >>> msgs[2].date\n datetime.datetime(2008, 7, 11, 13, 2, 11)\n >>> msgs[2].text\n 'Test message'\n\nAfter you receive messages you'll want to delete them from the SIM\ncard. This is done by calling the delete method on the messages.\n\n >>> msgs[0].delete()\n\nLet's test this by taking a look at the AT commands sent to the modem\nwhen a message is deleted.\n\n >>> m.conn.reset()\n >>> msgs[0].delete()\n >>> m.conn.sent()\n 'AT+CMGD=1\\r\\n'\n\n >>> m.conn.reset()\n >>> msgs[1].delete()\n >>> m.conn.sent()\n 'AT+CMGD=2\\r\\n'\n\nRather than polling the modem to find messages you can call the wait()\nmethod, which blocks until a message is received. The wait method\ntakes an optional timeout argument.\n\nFor the purposes of this test rather than actually blocking, the\nconnection will print how many seconds it would block for.\n\n >>> m.wait(1)\n reading with 1 timeout\n\n >>> m.wait()\n reading with no timeout\n\nThe wait message doesn't return anything. You should call the\nmessages() method after it returns to receive the messages. Note that\nit's possible that there may in fact be no messages available after\nthe wait method returns.\n\n\nMessage Decoding\n----------------\n\nMost of the time you can treat SMS messages as ASCII strings. However\nthey are supposedly in GMS 03.38 7bit encoding. I have never seen this\nin practice.\n\nI have seen unicode messages. They are encoded as a series of hex\nnumbers like so:\n\n >>> text = \"004500200074006500730074002000E800E9002000C800C90020006100200074006500730074002000C000C1002000E000E1\"\n\nThere is a function to decode these messages.\n\n >>> import sms.encoding\n >>> sms.encoding.decode_unicode(text)\n u'E test \\xe8\\xe9 \\xc8\\xc9 a test \\xc0\\xc1 \\xe0\\xe1'\n\nIt will fail if you try to feed it text that doesn't appear to be a unicode message.\n\n >>> sms.encoding.decode_unicode('not a unicode message')\n Traceback (most recent call last):\n ...\n ValueError: Message is not unicode\n\nI have also observered accented characters mixed in with ascii\ncharacters. The accented characters are values above 127. I don't know\nwhat encoding they are in, but I've reverse engineered it and it works\nfor me.\n\nHere's an example:\n\n >>> text = \"Montr\\x82al\"\n\nThe decode_accents function will decode these messages into unicode as\nbest it can.\n\n >>> sms.encoding.decode_accents(text)\n u'Montr\\xe9al'\n\nThe decode_accents function won't fail with unknown characters. It\nwill simply replace them with the unicode replacement character.\n\n >>> sms.encoding.decode_accents('what is this \\xff')\n u'what is this \\ufffd'\n\nThere's also a convenience to_ascii function to turn unicode into\nascii. It uses Fredrick Lundh's unaccent script.\n\n >>> sms.encoding.to_ascii(u'Montr\\xe9al')\n 'Montreal'\n\nCharacters that can't be easily turned into ascii are changed to ?.\n\n >>> sms.encoding.to_ascii(u'\\ufffd')\n '?'", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://pypi.python.org/pypi/sms", "keywords": null, "license": "MIT", "maintainer": null, "maintainer_email": null, "name": "sms", "package_url": "https://pypi.org/project/sms/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/sms/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://pypi.python.org/pypi/sms" }, "release_url": "https://pypi.org/project/sms/0.4/", "requires_dist": null, "requires_python": null, "summary": "SMS sending and receiving with enfora gsm modems", "version": "0.4" }, "last_serial": 799747, "releases": { "0.2": [ { "comment_text": "", "digests": { "md5": "dfe713c1b231048f339af11eb4394f60", "sha256": "2224fdd2256810b9c04c04917e60b03629c7de0fd2b05b57c030d6133d5ac3a1" }, "downloads": -1, "filename": "sms-0.2.tar.gz", "has_sig": false, "md5_digest": "dfe713c1b231048f339af11eb4394f60", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5188, "upload_time": "2008-09-19T18:33:14", "url": "https://files.pythonhosted.org/packages/29/ce/f8df0cf13d0e6fae688d09ecd07496faea26bf62d8ea126440a574be7d92/sms-0.2.tar.gz" } ], "0.3": [ { "comment_text": "", "digests": { "md5": "fd23d99549101b3bf98c9f0b807bc95a", "sha256": "7db0355884c0c187a489b3ca8ce121524d09bd526e333d880049cbf01a23afcb" }, "downloads": -1, "filename": "sms-0.3.tar.gz", "has_sig": false, "md5_digest": "fd23d99549101b3bf98c9f0b807bc95a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5197, "upload_time": "2008-09-19T18:38:41", "url": "https://files.pythonhosted.org/packages/51/a0/17b060982f88f007dc809ca36ff0d33b60cb75ed8cc57e12360b960ba8fc/sms-0.3.tar.gz" } ], "0.4": [ { "comment_text": "", "digests": { "md5": "074fba15815741579b8be4a47681c697", "sha256": "0da1a5e4cd673b58198f932685a5a1e2f330a22f91790ff0ee70c9b940f4cde7" }, "downloads": -1, "filename": "sms-0.4.tar.gz", "has_sig": false, "md5_digest": "074fba15815741579b8be4a47681c697", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8860, "upload_time": "2010-04-24T17:57:24", "url": "https://files.pythonhosted.org/packages/91/ea/cadc987bb2e74df153349df84dac2ba34d2752fb943e6660430061dab2f9/sms-0.4.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "074fba15815741579b8be4a47681c697", "sha256": "0da1a5e4cd673b58198f932685a5a1e2f330a22f91790ff0ee70c9b940f4cde7" }, "downloads": -1, "filename": "sms-0.4.tar.gz", "has_sig": false, "md5_digest": "074fba15815741579b8be4a47681c697", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8860, "upload_time": "2010-04-24T17:57:24", "url": "https://files.pythonhosted.org/packages/91/ea/cadc987bb2e74df153349df84dac2ba34d2752fb943e6660430061dab2f9/sms-0.4.tar.gz" } ] }