123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582 |
- #!/usr/bin/env python2
- #
- # @MASTER@
- # @GENERATED@
- #
- # This is the CGI that processes the form return from GPS information form.
- #
- # The wackiness with output_sample_com happens because the user has to click
- # through twice - once to review and once to submit. Thus the content has
- # to be embedded as a hidden field - and base64-armored, because it might
- # otherwise have stuff in it that isn't legal in HTML attribute values.
- #
- import sys, os, smtplib, base64
- from email.mime.text import MIMEText
- from email.mime.multipart import MIMEMultipart
- from email.encoders import encode_base64
- import cgi
- import cgitb; cgitb.enable() # for troubleshooting
- # All information on the project siting, mailing
- # lists, and originating host lives here.
- website = '@WEBSITE@'
- to_address = '@DEVMAIL@'
- servaddr = '@FORMSERVER@'
- # Get form value, send mail on submission
- form = cgi.FieldStorage()
- print "Content-type: text/html"
- print ""
- if form.has_key('output_sample_content'):
- output_sample_content = base64.b64decode(form.getvalue('output_sample_content'))
- else:
- output_sample_content = ''
- if not output_sample_content and form.has_key('output_sample_file'):
- fileitem = form['output_sample_file']
- if fileitem.filename:
- output_sample_content = fileitem.file.read()
- def hasRequiredElements(form):
- for fld in ("submitter", "vendor", "model", "techdoc"):
- if not form.getvalue(fld):
- return False
- return not not output_sample_content
- formfields = ("submitter",
- "vendor",
- "model",
- "techdoc",
- "packaging",
- "chipset",
- "firmware",
- "nmea",
- "interfaces",
- "usbchip",
- "tested",
- "rating",
- "configurable",
- "output_sample_file",
- "output_sample_content",
- "location",
- "date",
- "sample_notes",
- )
- if hasRequiredElements(form) and form.getvalue("action") == "Send Report":
- report = MIMEMultipart()
- report['Subject'] = 'New device report'
- report['To'] = to_address
- report.preamble = "Part 1 is form data, part 2 is the sample"
- # Render the form data as an entry for gpscap.ini
- msg = "[%s]\n" % form.getvalue('model').strip()
- for field in formfields:
- if form.getvalue(field) and not field == 'model' and not field.startswith('output_sample'):
- msg += "%s: %s\n" % (field, form.getvalue(field))
- report.attach(MIMEText(msg))
- # Decorate the log data with some canned headers.
- # Omitted: nmea, notes, techdoc, tested, usbchip, configurable,
- header = ''
- header += "# Name: %s %s\n" \
- % (form.getvalue('vendor'), form.getvalue('model'))
- for fld in ("chipset", "firmware", 'date', 'submitter', 'location'):
- if form.has_key(fld) and form.getvalue(fld):
- header += "# %s = %s\n" % (fld.capitalize(), form.getvalue(fld))
- if form.has_key('sample_notes') and form.getvalue('sample_notes'):
- header += "# Notes: %s\n" % form.getvalue('sample_notes')
- header += "type = device\n"
- content = MIMEText(header + output_sample_content)
- encode_base64(content)
- report.attach(content)
- # Ship it.
- msg = report.as_string()
- smtp = smtplib.SMTP("localhost")
- #smtp.set_debuglevel(1)
- try:
- smtp.sendmail(servaddr, [to_address], msg)
- smtp.quit()
- print "<H1>New device report accepted.</H1>\n"
- print "<p>Your report on the %s %s was successfully recorded. Thanks for helping improve GPSD.\n" \
- % (form.getvalue('vendor'), form.getvalue('model'))
- except smtplib.SMTPSenderRefused, e:
- print "<H1>Your submission failed.</H1>\n"
- print "<p>The error code was %s: %s</p>" % (e.code, e.response)
- sys.exit(0)
- # Everything below here is page generation
- defaults = {}
- for key in formfields:
- if key in form.keys():
- defaults[key] = form.getvalue(key).strip()
- else:
- defaults[key] = ""
- defaults['request_uri'] = os.getenv('REQUEST_URI')
- defaults["website"] = website
- defaults["to_address"] = to_address
- defaults["servaddr"] = servaddr
- defaults['output_sample_content'] = output_sample_content
- defaults['armored_sample_content'] = base64.b64encode(output_sample_content)
- print '''\
- <!DOCTYPE HTML>
- <html lang="en">
- <head lang="en">
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <meta name="Author" content="Eric S. Raymond">
- <meta name="Description" content="Report the GPSD compatibility of your GPS.">
- <meta name="Keywords" content="GPS, gpsd,report">
- <meta name="Revised" content="9 Apr 2015">
- <meta name="robots" content="index,follow">
- <title></title>
- <link rel="stylesheet" href="main.css" type="text/css">
- </head>
- <body>
- <div id="Content">
- <h1>GPSD Receiver Reporting Form</h1>
- <p>Please use this form to report <code>gpsd</code> successes or
- failures with GPS and AIS units, and also to upload a sample of the receiver\'s
- output so we can add it to our regression tests and ensure continued
- support of the device.</p>
- <p>Information gathered so far:</p>
- <table style="border:0;width:100%"><tr><td style="text-align:center">
- '''
- if form.getvalue("vendor"):
- print "Vendor is <code>"+cgi.escape(form.getvalue("vendor"))+"</code><br>\n";
- else:
- print "<span style='color:#ff0000;'>No vendor.</span><br>\n";
- if form.getvalue("model"):
- print "Model is <code>"+cgi.escape(form.getvalue("model"))+"</code><br>\n";
- else:
- print "<span style='color:#ff0000;'>No model specified.</span><br>\n";
- if form.getvalue("techdoc"):
- print "<a href='"+cgi.escape(form.getvalue("techdoc"))+"'>Document URL specified.</a><br>\n";
- else:
- print "<span style='color:#ff0000;'>No document URL.</span><br>\n";
- if output_sample_content:
- print "Output sample uploaded";
- else:
- print "<span style='color:#ff0000;'>No output sample.</span><br>\n";
- if form.getvalue("submitter"):
- print "Contact address is <code>"+cgi.escape(form.getvalue("submitter"))+"</code><br>\n";
- else:
- print "<span style='color:#ff0000;'>No contact address.</span><br>\n";
- print "</td><td style='text-align:center'>";
- if form.getvalue("packaging"):
- print "Packaging type is <code>"+cgi.escape(form.getvalue("packaging"))+"</code><br>\n";
- else:
- print "No packaging type specified.<br>\n";
- if form.getvalue("chipset"):
- print "Chipset is <code>"+cgi.escape(form.getvalue("chipset"))+"</code><br>\n";
- else:
- print "Chipset not specified.<br>\n";
- if form.getvalue("firmware"):
- print "Firmware is <code>"+cgi.escape(form.getvalue("firmware"))+"</code><br>\n";
- else:
- print "Firmware not specified.<br>\n";
- if form.getvalue("nmea"):
- print "NMEA version is <code>"+cgi.escape(form.getvalue("nmea"))+"</code><br>\n";
- else:
- print "NMEA version not specified.<br>\n";
- if form.getvalue("interfaces"):
- print "Interface type is <code>"+cgi.escape(form.getvalue("interfaces"))+"</code><br>\n";
- if form.getvalue("interfaces") == "USB":
- if form.getvalue("usbchip"):
- print "USB chip is <code>"+cgi.escape(form.getvalue("usbchip"))+"</code><br>\n";
- else:
- print "No USB chip specified.<br>\n";
- else:
- print "No interface type specified.<br>\n";
- if form.getvalue("tested"):
- print "Tested with GPSD version <code>"+cgi.escape(form.getvalue("tested"))+"</code><br>\n";
- else:
- print "No GPSD version specified.<br>\n";
- print "</td><td style='text-align:center'>";
- if form.getvalue("rating"):
- print "GPSD compatibility is <code>"+cgi.escape(form.getvalue("rating"))+"</code><br>\n";
- else:
- print "No GPSD compatibility specified.<br>\n";
- if form.getvalue("noconfigure") == 'yes':
- print "Device can be sent catatonic by baud-rate changes.<br>\n";
- elif form.getvalue("noconfigure") == 'no':
- print "Device handles baud-rate changes correctly.<br>\n";
- else:
- print "How baud-rate changes are handled is unspecified.<br>\n";
- if form.getvalue("notes"):
- print "Technical notes have been entered.<br>\n";
- else:
- print "No technical notes.<br>\n";
- if form.getvalue("location"):
- print "Sample location <code>"+cgi.escape(form.getvalue("location"))+"</code><br>\n";
- else:
- print "No sample location specified.<br>\n";
- if form.getvalue("date"):
- print "Sample date <code>"+cgi.escape(form.getvalue("date"))+"</code><br>\n";
- else:
- print "No sample date specified.<br>\n";
- if form.getvalue("sample_notes"):
- print "Notes on the sample have been entered.<br>\n";
- else:
- print "No notes on the sample.<br>\n";
- print "</td></tr></table>";
- if hasRequiredElements(form):
- print '<p>The report is ready to be submitted.</p>'
- else:
- print '<p style="color:#ff0000;">Required fields are missing; please fill them in.</p>'
- print '''
- <form action="%(request_uri)s" method=POST enctype="multipart/form-data">
- <p>Fields marked <em style="color: #ff0000;">Important!</em> have to be filled
- in for the report to be useful. These are: submitter contact address, vendor,
- model, documentation URL, and output sample. Other fields represent things we
- might be able to find out ourselves, but which are easier for you to determine.
- Every bit of information you can give us about your receiver will help make the
- support for it more reliable.</p>
- <hr>
- <h2>Receiver type identification</h2>
- <p><em style="color: #ff0000;">Important!</em> Identify the vendor and model of
- your device.</p>
- <p>Example: <code>Haicom</code> and <code>303S</code>.</p>
- <p><em>Vendor: </em>
- <input type="text"
- name="vendor"
- size="72"
- value="%(vendor)s"></p>
- <p><em>Model: </em>
- <input type="text"
- name="model"
- size="72"
- value="%(model)s"></p>
- <p><em style="color: #ff0000;">Important!</em> We need a URL pointing to a
- technical manual for the device. You can usually find this on the
- vendor\'s website by giving a search engine the product name. If it\'s
- not linked directly from the vendor\'s page for the individual product,
- look under "Technical Support" or "Product support" on the vendor\'s
- main page.</p>
- <p>Example: <code>http://www.haicom.com.tw/gps303s.shtml</code></p>
- <p><em>URL of a technical manual:</em>
- <input type="text"
- name="techdoc"
- size="72"
- value="%(techdoc)s"></p>
- <p>It is useful to have an indication of how the receiver is packaged.
- <p><em>Packaging:</em></p>
- ''' % defaults
- packagetypes = (
- ('mouse', 'A "mouse" is a standalone sensor in a display-less case '
- 'designed to be used as a peripheral cabled to a computer.'),
- ('dongle', 'A "dongle" is a standalone sensor in a display-less case '
- 'resembling a thumb drive intended to be plugged directly '
- 'into a USB port.'),
- ('handset', 'A "handset" is a standalone unit with a display and '
- 'human-usable controls.'),
- ('handsfree', 'A "handsfree" is a hands-free unit with display designed '
- 'for mounting on a car windshield or boat console.'),
- ('survey', 'A "survey" unit is packaged for field-survey use.'),
- ('OEM module','An "OEM module" is an un-cased circuit board with edge '
- 'connectors.'),
- ('chipset', 'A "chipset" is a bare chip or chips packaged for surface '
- 'mount.'),
- ('other', 'None of the above'),
- )
- for (ptype, plegend) in packagetypes:
- print '<input type="radio" name="packaging" value="%s">%s<br/>' % (ptype, plegend)
- print '''
- <p>Please identify the device chipset and firmware version, if possible. You
- may be able to get this from the display of <code>xgps</code>; look for
- a Device Type field or at the window title bar. Alternatively, you may find
- it in the technical manual.</p>
- <p>Example: <code>SiRF-II</code> and <code>2.31ES</code>.</p>
- <p><em>Chipset: </em>
- <input type="text"
- name="chipset"
- size="72"
- value="%(chipset)s"></p>
- <p><em>Firmware: </em>
- <input type="text"
- name="firmware"
- size="72"
- value="%(firmware)s"></p>
- <p>Please identify, if possible, the NMEA version the receiver emits. You may
- be able to get this information from the technical manual. Likely values are
- <code>2.0</code>, <code>2.2</code>, <code>2.3</code>, <code>3.0</code>, and
- <code>2000</code> for NMEA2000 devices. If the GPS emits only a vendor binary
- protocol, leave this field blank.</p>
- <p><em>NMEA version emitted: </em>
- <input type="text"
- name="nmea"
- size="6"
- value="%(nmea)s"></p>
- <hr/>
- <h2>Interfaces</h2>
- <p>Please identify the receiver\'s interface type (USB, RS-232, Bluetooth,
- Compact Flash, CAN bus, etc.). If the receiver has adapters that support other
- interfaces, tell us the one you have and mention the adapters in the "Technical
- Notes" box. If it has an exotic interface not listed here, select "Other" and
- tell us about it in "Technical Notes".</p>
- ''' % defaults
- ifline = '<td><input type="radio" name="interfaces" value="%s">%s</td>'
- print "<table style='border:1'><tr>"
- for itype in ('USB', 'Bluetooth', 'Compact Flash', 'RS-232', 'TTL', 'CAN', 'Other'):
- print ifline % (itype, itype)
- print "</tr></table>"
- print '''
- <p>If your device is USB, it probably uses a USB-to-serial adapter
- chip. Try to find out what this is by looking at the output of
- <code>lsusb(1)</code>.</p>
- '''
- cline = '<td><input type="radio" name="interfaces" value="%s">%s</td>'
- print "<table style='border:1'><tr>"
- for ctype in ('PL2303', 'UC-232A', 'FTDI', 'Cypress M8', 'CP210x', 'Other'):
- print cline % (ctype, ctype)
- print "</tr></table>"
- print '''
- <hr>
- <h2>GPSD compatibility</h2>
- <p>Please tell us what version you tested with. If you used a published
- release, give us the full release number, like <code>3.5</code>. If you built
- your code from our development repository, please give the revision ID.</p>
- <p><em>GPSD version: </em>
- <input type="text"
- name="tested"
- size="6"
- value="%(tested)s"></p>
- <p>Please rate how well this receiver functions with GPSD:</p>
- ''' % defaults
- ratings = (
- ("excellent",
- "Excellent -- gpsd recognizes the receiver rapidly and reliably, reports are complete and correct."),
- ("good",
- "Good -- gpsd has minor problems or lag recognizing the device, but reports are complete and correct."),
- ("fair",
- "Fair -- Reports have minor dropouts or problems, including occasional transient nonsense values."),
- ("poor",
- "Poor -- Reports frequently have values that are wrong or nonsense."),
- ("broken",
- "Broken -- gpsd frequently, or always, fails to recognize the device at all."),
- ("other",
- "Other -- See Technical Notes."),
- )
- rateline = '<input type="radio" name="rating" value="%s"%s>%s<br/>'
- for (rtype, rlegend) in ratings:
- if defaults['packaging'] == rtype:
- print rateline % (rtype, " checked", rlegend)
- else:
- print rateline % (rtype, "", rlegend)
- print '<p>Device sanity when probed or speed-switched:<br/>'
- sanity = (('sane', 'Sane: accepts baud-rate changes and probes.'),
- ('insane', 'Insane: goes catatonic on baud-rate changes and probes.'))
- saneline = '<input type="radio" name="sanity" value="%s"%s>%s<br/>'
- for (stype, slegend) in sanity:
- if defaults['configurable'] == stype:
- print saneline % (stype, " checked", slegend)
- else:
- print saneline % (stype, "", slegend)
- print '''
- <hr>
- <h2>Technical notes</h2>
- <p>Now tell us the things that didn\'t fit in the rest of the form.
- Appropriate things to put here include how to read any LEDs or other
- unlabeled indicators on the device, a warning that the product has
- been discontinued, a list of alternate interfaces, descriptions of
- errors in the documentation, descriptions of
- special abilities such as the ability to vary the sampling interval,
- and a note if it\'s an OEM module rather than a retail product.
- Anything else you think we need to know should go here too.</p>
- <textarea name="notes" rows="10", cols="72"></textarea>
- <hr>
- <h2>Output sample</h2>
- <p><em style=\'color: #ff0000;\'>Important!</em> We need a sample of the output
- from your receiver - not the gpsd logfile, just raw output. We\'ll use this for
- mechanical regression testing, which is your best guarantee that support for
- your device won\'t get broken in a future release. Please be advised that these
- logs will be sent to a publicly archived mailing list, and will be available in
- the public code repository.</p>
- <p>Almost all receivers will simply start throwing data to your port
- immediately when they\'re plugged in. You should normally be able to capture
- this output to a file with the <code>gpscat</code> utility.</p>
- <p>There will be some unusual cases in which this isn\'t possible,
- because the device needs some kind of activation sequence written to
- it before it will start reporting. Some Garmin GPSes (the ones that
- speak Garmin binary protocol rather than NMEA) are like this. If you
- think you have one of these, ask for help on GPSD\'s development mailing
- list</a>.</p>
- <p>A log file is most useful when it contains (a) some sentences
- generated when the receiver has no fix, (b) some sentences representing
- a fix with the unit stationary, and (c) some sentences representing
- a fix with the unit moving.</p>
- <input type="file" name="output_sample_file">
- <input type="hidden" name="output_sample_content" value="%(armored_sample_content)s">
- <p>There is some auxiliary data we like to have in our regression-test
- files.</p>
- <p>Location of the log capture. A good format would include your
- nearest city or other landmark, state/province, country code, and a
- rough latitude/longitude. A GPS will give an exact location; we
- want this as a sanity check.</p>
- <p>Example: <code>Groningen, NL, 53.2N 6.6E</code></p>
- <p><em>Location: </em>
- <input type="text"
- name="location"
- size="72"
- value="%(location)s"></p>
- <p>Year-Month-Day of the log capture (the receiver will give us
- hour/minute/second).</p>
- <p>Example: <code>2011-05-14</code>.</p>
- <p><em>Date: </em>
- <input type="text"
- name="date"
- size="72"
- value="%(date)s"></p>
- <p>Finally, add any notes you want to about how the sample was taken. One
- good thing to put here would a description of how the unit was moving while the
- log was being captured. If the sentence mix changes between "fix" and "no fix"
- states, that too is a good thing to note.</p>
- <textarea name="sample_notes" rows="10", cols="72"></textarea>
- <hr>
- <h2>Contact information</h2>
- <p><em style="color: #ff0000;">Important!</em> We need a valid email
- address for you in case we need to ask you followup questions about
- the device. While we won\'t use your address for anything other than
- asking you questions about your receiver, and maybe asking you to test
- specific changes, this device report will be sent to the gpsd-dev list
- which is publicly archived.</p>
- <p>Example: <code>Eric Raymond <esr@thyrsus.com></code></p>
- <p><em>Name and email address: </em>
- <input type="text"
- name="submitter"
- size="72"
- value="%(submitter)s"></p>
- <p>(It is not actually very likely we will contact you, but we need to
- be able to do it if we can find no other way of getting information
- about the device. Expect to hear from us if your receiver is obsolescent or
- exotic and the information you provide in the rest of this form turns
- out to be insufficient. Or if your browser is broken enough to botch
- the output-sample upload.)</p>
- <hr>
- ''' % defaults
- print "<p>To see what you have entered so far, click <code>Review</code>\n";
- # Must have all critical fields to ship
- if hasRequiredElements(form):
- print '''
- <p>Click the <code>Send Report</code> button to send your report to the GPSD
- developers. Eventually, your report is likely to appear on our <a
- href="%(website)s/hardware.html">Hardware</a> page.</p>
- <table style="width:100%%;border:0">
- <tr>
- <td style="text-align:center">
- <a href="%(request_uri)s">Reset Form</a>
- <input type="submit" name="action" value="Review">
- <input type="submit" name="action" value="Send Report">
- </td>
- </tr>
- </table>
- ''' % defaults
- else:
- print '''
- <p style="color:#ff0000;">Required fields are missing; please fill them in.</p>
- <table style="width:100%%;border:0">
- <tr>
- <td style="text-align:center">
- <a href="%(request_uri)s">Reset Form</a>
- <input type="submit" name="action" value="Review">
- </td>
- </tr>
- </table>
- ''' % defaults
- print '''
- </form>
- </div>
- '''
- # The following sets edit modes for GNU EMACS
- # Local Variables:
- # mode: python
- # fill-column:79
- # End:
|