Guest User

Untitled

a guest
Aug 20th, 2016
136
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 25.85 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # Copyright 2012-2015 Matt Martz
  4. # All Rights Reserved.
  5. #
  6. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  7. # not use this file except in compliance with the License. You may obtain
  8. # a copy of the License at
  9. #
  10. # http://www.apache.org/licenses/LICENSE-2.0
  11. #
  12. # Unless required by applicable law or agreed to in writing, software
  13. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  14. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  15. # License for the specific language governing permissions and limitations
  16. # under the License.
  17.  
  18. import os
  19. import re
  20. import sys
  21. import math
  22. import signal
  23. import socket
  24. import timeit
  25. import platform
  26. import threading
  27. import paho.mqtt.client as mqtt
  28. mqttc = mqtt.Client("speed_python_pub")
  29. mqttc.username_pw_set("mqtt_username","mqtt_password")
  30. mqttc.connect("mqtt_server_address", 1883)
  31.  
  32. __version__ = '0.3.4'
  33.  
  34. # Some global variables we use
  35. user_agent = None
  36. source = None
  37. shutdown_event = None
  38. scheme = 'http'
  39.  
  40. # Used for bound_interface
  41. socket_socket = socket.socket
  42.  
  43. try:
  44. import xml.etree.cElementTree as ET
  45. except ImportError:
  46. try:
  47. import xml.etree.ElementTree as ET
  48. except ImportError:
  49. from xml.dom import minidom as DOM
  50. ET = None
  51.  
  52. # Begin import game to handle Python 2 and Python 3
  53. try:
  54. from urllib2 import urlopen, Request, HTTPError, URLError
  55. except ImportError:
  56. from urllib.request import urlopen, Request, HTTPError, URLError
  57.  
  58. try:
  59. from httplib import HTTPConnection, HTTPSConnection
  60. except ImportError:
  61. e_http_py2 = sys.exc_info()
  62. try:
  63. from http.client import HTTPConnection, HTTPSConnection
  64. except ImportError:
  65. e_http_py3 = sys.exc_info()
  66. raise SystemExit('Your python installation is missing required HTTP '
  67. 'client classes:\n\n'
  68. 'Python 2: %s\n'
  69. 'Python 3: %s' % (e_http_py2[1], e_http_py3[1]))
  70.  
  71. try:
  72. from Queue import Queue
  73. except ImportError:
  74. from queue import Queue
  75.  
  76. try:
  77. from urlparse import urlparse
  78. except ImportError:
  79. from urllib.parse import urlparse
  80.  
  81. try:
  82. from urlparse import parse_qs
  83. except ImportError:
  84. try:
  85. from urllib.parse import parse_qs
  86. except ImportError:
  87. from cgi import parse_qs
  88.  
  89. try:
  90. from hashlib import md5
  91. except ImportError:
  92. from md5 import md5
  93.  
  94. try:
  95. from argparse import ArgumentParser as ArgParser
  96. except ImportError:
  97. from optparse import OptionParser as ArgParser
  98.  
  99. try:
  100. import builtins
  101. except ImportError:
  102. def print_(*args, **kwargs):
  103. """The new-style print function taken from
  104. https://pypi.python.org/pypi/six/
  105.  
  106. """
  107. fp = kwargs.pop("file", sys.stdout)
  108. if fp is None:
  109. return
  110.  
  111. def write(data):
  112. if not isinstance(data, basestring):
  113. data = str(data)
  114. fp.write(data)
  115.  
  116. want_unicode = False
  117. sep = kwargs.pop("sep", None)
  118. if sep is not None:
  119. if isinstance(sep, unicode):
  120. want_unicode = True
  121. elif not isinstance(sep, str):
  122. raise TypeError("sep must be None or a string")
  123. end = kwargs.pop("end", None)
  124. if end is not None:
  125. if isinstance(end, unicode):
  126. want_unicode = True
  127. elif not isinstance(end, str):
  128. raise TypeError("end must be None or a string")
  129. if kwargs:
  130. raise TypeError("invalid keyword arguments to print()")
  131. if not want_unicode:
  132. for arg in args:
  133. if isinstance(arg, unicode):
  134. want_unicode = True
  135. break
  136. if want_unicode:
  137. newline = unicode("\n")
  138. space = unicode(" ")
  139. else:
  140. newline = "\n"
  141. space = " "
  142. if sep is None:
  143. sep = space
  144. if end is None:
  145. end = newline
  146. for i, arg in enumerate(args):
  147. if i:
  148. write(sep)
  149. write(arg)
  150. write(end)
  151. else:
  152. print_ = getattr(builtins, 'print')
  153. del builtins
  154.  
  155.  
  156. class SpeedtestCliServerListError(Exception):
  157. """Internal Exception class used to indicate to move on to the next
  158. URL for retrieving speedtest.net server details
  159.  
  160. """
  161.  
  162.  
  163. def bound_socket(*args, **kwargs):
  164. """Bind socket to a specified source IP address"""
  165.  
  166. global source
  167. sock = socket_socket(*args, **kwargs)
  168. sock.bind((source, 0))
  169. return sock
  170.  
  171.  
  172. def distance(origin, destination):
  173. """Determine distance between 2 sets of [lat,lon] in km"""
  174.  
  175. lat1, lon1 = origin
  176. lat2, lon2 = destination
  177. radius = 6371 # km
  178.  
  179. dlat = math.radians(lat2 - lat1)
  180. dlon = math.radians(lon2 - lon1)
  181. a = (math.sin(dlat / 2) * math.sin(dlat / 2) +
  182. math.cos(math.radians(lat1)) *
  183. math.cos(math.radians(lat2)) * math.sin(dlon / 2) *
  184. math.sin(dlon / 2))
  185. c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
  186. d = radius * c
  187.  
  188. return d
  189.  
  190.  
  191. def build_user_agent():
  192. """Build a Mozilla/5.0 compatible User-Agent string"""
  193.  
  194. global user_agent
  195. if user_agent:
  196. return user_agent
  197.  
  198. ua_tuple = (
  199. 'Mozilla/5.0',
  200. '(%s; U; %s; en-us)' % (platform.system(), platform.architecture()[0]),
  201. 'Python/%s' % platform.python_version(),
  202. '(KHTML, like Gecko)',
  203. 'speedtest-cli/%s' % __version__
  204. )
  205. user_agent = ' '.join(ua_tuple)
  206. return user_agent
  207.  
  208.  
  209. def build_request(url, data=None, headers={}):
  210. """Build a urllib2 request object
  211.  
  212. This function automatically adds a User-Agent header to all requests
  213.  
  214. """
  215.  
  216. if url[0] == ':':
  217. schemed_url = '%s%s' % (scheme, url)
  218. else:
  219. schemed_url = url
  220.  
  221. headers['User-Agent'] = user_agent
  222. return Request(schemed_url, data=data, headers=headers)
  223.  
  224.  
  225. def catch_request(request):
  226. """Helper function to catch common exceptions encountered when
  227. establishing a connection with a HTTP/HTTPS request
  228.  
  229. """
  230.  
  231. try:
  232. uh = urlopen(request)
  233. return uh, False
  234. except (HTTPError, URLError, socket.error):
  235. e = sys.exc_info()[1]
  236. return None, e
  237.  
  238.  
  239. class FileGetter(threading.Thread):
  240. """Thread class for retrieving a URL"""
  241.  
  242. def __init__(self, url, start):
  243. self.url = url
  244. self.result = None
  245. self.starttime = start
  246. threading.Thread.__init__(self)
  247.  
  248. def run(self):
  249. self.result = [0]
  250. try:
  251. if (timeit.default_timer() - self.starttime) <= 10:
  252. request = build_request(self.url)
  253. f = urlopen(request)
  254. while 1 and not shutdown_event.isSet():
  255. self.result.append(len(f.read(10240)))
  256. if self.result[-1] == 0:
  257. break
  258. f.close()
  259. except IOError:
  260. pass
  261.  
  262.  
  263. def downloadSpeed(files, quiet=False):
  264. """Function to launch FileGetter threads and calculate download speeds"""
  265.  
  266. start = timeit.default_timer()
  267.  
  268. def producer(q, files):
  269. for file in files:
  270. thread = FileGetter(file, start)
  271. thread.start()
  272. q.put(thread, True)
  273. if not quiet and not shutdown_event.isSet():
  274. sys.stdout.write('.')
  275. sys.stdout.flush()
  276.  
  277. finished = []
  278.  
  279. def consumer(q, total_files):
  280. while len(finished) < total_files:
  281. thread = q.get(True)
  282. while thread.isAlive():
  283. thread.join(timeout=0.1)
  284. finished.append(sum(thread.result))
  285. del thread
  286.  
  287. q = Queue(6)
  288. prod_thread = threading.Thread(target=producer, args=(q, files))
  289. cons_thread = threading.Thread(target=consumer, args=(q, len(files)))
  290. start = timeit.default_timer()
  291. prod_thread.start()
  292. cons_thread.start()
  293. while prod_thread.isAlive():
  294. prod_thread.join(timeout=0.1)
  295. while cons_thread.isAlive():
  296. cons_thread.join(timeout=0.1)
  297. return (sum(finished) / (timeit.default_timer() - start))
  298.  
  299.  
  300. class FilePutter(threading.Thread):
  301. """Thread class for putting a URL"""
  302.  
  303. def __init__(self, url, start, size):
  304. self.url = url
  305. chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  306. data = chars * (int(round(int(size) / 36.0)))
  307. self.data = ('content1=%s' % data[0:int(size) - 9]).encode()
  308. del data
  309. self.result = None
  310. self.starttime = start
  311. threading.Thread.__init__(self)
  312.  
  313. def run(self):
  314. try:
  315. if ((timeit.default_timer() - self.starttime) <= 10 and
  316. not shutdown_event.isSet()):
  317. request = build_request(self.url, data=self.data)
  318. f = urlopen(request)
  319. f.read(11)
  320. f.close()
  321. self.result = len(self.data)
  322. else:
  323. self.result = 0
  324. except IOError:
  325. self.result = 0
  326.  
  327.  
  328. def uploadSpeed(url, sizes, quiet=False):
  329. """Function to launch FilePutter threads and calculate upload speeds"""
  330.  
  331. start = timeit.default_timer()
  332.  
  333. def producer(q, sizes):
  334. for size in sizes:
  335. thread = FilePutter(url, start, size)
  336. thread.start()
  337. q.put(thread, True)
  338. if not quiet and not shutdown_event.isSet():
  339. sys.stdout.write('.')
  340. sys.stdout.flush()
  341.  
  342. finished = []
  343.  
  344. def consumer(q, total_sizes):
  345. while len(finished) < total_sizes:
  346. thread = q.get(True)
  347. while thread.isAlive():
  348. thread.join(timeout=0.1)
  349. finished.append(thread.result)
  350. del thread
  351.  
  352. q = Queue(6)
  353. prod_thread = threading.Thread(target=producer, args=(q, sizes))
  354. cons_thread = threading.Thread(target=consumer, args=(q, len(sizes)))
  355. start = timeit.default_timer()
  356. prod_thread.start()
  357. cons_thread.start()
  358. while prod_thread.isAlive():
  359. prod_thread.join(timeout=0.1)
  360. while cons_thread.isAlive():
  361. cons_thread.join(timeout=0.1)
  362. return (sum(finished) / (timeit.default_timer() - start))
  363.  
  364.  
  365. def getAttributesByTagName(dom, tagName):
  366. """Retrieve an attribute from an XML document and return it in a
  367. consistent format
  368.  
  369. Only used with xml.dom.minidom, which is likely only to be used
  370. with python versions older than 2.5
  371. """
  372. elem = dom.getElementsByTagName(tagName)[0]
  373. return dict(list(elem.attributes.items()))
  374.  
  375.  
  376. def getConfig():
  377. """Download the speedtest.net configuration and return only the data
  378. we are interested in
  379. """
  380.  
  381. request = build_request('://www.speedtest.net/speedtest-config.php')
  382. uh, e = catch_request(request)
  383. if e:
  384. print_('Could not retrieve speedtest.net configuration: %s' % e)
  385. sys.exit(1)
  386. configxml = []
  387. while 1:
  388. configxml.append(uh.read(10240))
  389. if len(configxml[-1]) == 0:
  390. break
  391. if int(uh.code) != 200:
  392. return None
  393. uh.close()
  394. try:
  395. try:
  396. root = ET.fromstring(''.encode().join(configxml))
  397. config = {
  398. 'client': root.find('client').attrib,
  399. 'times': root.find('times').attrib,
  400. 'download': root.find('download').attrib,
  401. 'upload': root.find('upload').attrib}
  402. except AttributeError: # Python3 branch
  403. root = DOM.parseString(''.join(configxml))
  404. config = {
  405. 'client': getAttributesByTagName(root, 'client'),
  406. 'times': getAttributesByTagName(root, 'times'),
  407. 'download': getAttributesByTagName(root, 'download'),
  408. 'upload': getAttributesByTagName(root, 'upload')}
  409. except SyntaxError:
  410. print_('Failed to parse speedtest.net configuration')
  411. sys.exit(1)
  412. del root
  413. del configxml
  414. return config
  415.  
  416.  
  417. def closestServers(client, all=False):
  418. """Determine the 5 closest speedtest.net servers based on geographic
  419. distance
  420. """
  421.  
  422. urls = [
  423. '://www.speedtest.net/speedtest-servers-static.php',
  424. '://c.speedtest.net/speedtest-servers-static.php',
  425. '://www.speedtest.net/speedtest-servers.php',
  426. '://c.speedtest.net/speedtest-servers.php',
  427. ]
  428. errors = []
  429. servers = {}
  430. for url in urls:
  431. try:
  432. request = build_request(url)
  433. uh, e = catch_request(request)
  434. if e:
  435. errors.append('%s' % e)
  436. raise SpeedtestCliServerListError
  437. serversxml = []
  438. while 1:
  439. serversxml.append(uh.read(10240))
  440. if len(serversxml[-1]) == 0:
  441. break
  442. if int(uh.code) != 200:
  443. uh.close()
  444. raise SpeedtestCliServerListError
  445. uh.close()
  446. try:
  447. try:
  448. root = ET.fromstring(''.encode().join(serversxml))
  449. elements = root.getiterator('server')
  450. except AttributeError: # Python3 branch
  451. root = DOM.parseString(''.join(serversxml))
  452. elements = root.getElementsByTagName('server')
  453. except SyntaxError:
  454. raise SpeedtestCliServerListError
  455. for server in elements:
  456. try:
  457. attrib = server.attrib
  458. except AttributeError:
  459. attrib = dict(list(server.attributes.items()))
  460. d = distance([float(client['lat']),
  461. float(client['lon'])],
  462. [float(attrib.get('lat')),
  463. float(attrib.get('lon'))])
  464. attrib['d'] = d
  465. if d not in servers:
  466. servers[d] = [attrib]
  467. else:
  468. servers[d].append(attrib)
  469. del root
  470. del serversxml
  471. del elements
  472. except SpeedtestCliServerListError:
  473. continue
  474.  
  475. # We were able to fetch and parse the list of speedtest.net servers
  476. if servers:
  477. break
  478.  
  479. if not servers:
  480. print_('Failed to retrieve list of speedtest.net servers:\n\n %s' %
  481. '\n'.join(errors))
  482. sys.exit(1)
  483.  
  484. closest = []
  485. for d in sorted(servers.keys()):
  486. for s in servers[d]:
  487. closest.append(s)
  488. if len(closest) == 5 and not all:
  489. break
  490. else:
  491. continue
  492. break
  493.  
  494. del servers
  495. return closest
  496.  
  497.  
  498. def getBestServer(servers):
  499. """Perform a speedtest.net latency request to determine which
  500. speedtest.net server has the lowest latency
  501. """
  502.  
  503. results = {}
  504. for server in servers:
  505. cum = []
  506. url = '%s/latency.txt' % os.path.dirname(server['url'])
  507. urlparts = urlparse(url)
  508. for i in range(0, 3):
  509. try:
  510. if urlparts[0] == 'https':
  511. h = HTTPSConnection(urlparts[1])
  512. else:
  513. h = HTTPConnection(urlparts[1])
  514. headers = {'User-Agent': user_agent}
  515. start = timeit.default_timer()
  516. h.request("GET", urlparts[2], headers=headers)
  517. r = h.getresponse()
  518. total = (timeit.default_timer() - start)
  519. except (HTTPError, URLError, socket.error):
  520. cum.append(3600)
  521. continue
  522. text = r.read(9)
  523. if int(r.status) == 200 and text == 'test=test'.encode():
  524. cum.append(total)
  525. else:
  526. cum.append(3600)
  527. h.close()
  528. avg = round((sum(cum) / 6) * 1000, 3)
  529. results[avg] = server
  530. fastest = sorted(results.keys())[0]
  531. best = results[fastest]
  532. best['latency'] = fastest
  533.  
  534. return best
  535.  
  536.  
  537. def ctrl_c(signum, frame):
  538. """Catch Ctrl-C key sequence and set a shutdown_event for our threaded
  539. operations
  540. """
  541.  
  542. global shutdown_event
  543. shutdown_event.set()
  544. raise SystemExit('\nCancelling...')
  545.  
  546.  
  547. def version():
  548. """Print the version"""
  549.  
  550. raise SystemExit(__version__)
  551.  
  552.  
  553. def speedtest():
  554. """Run the full speedtest.net test"""
  555.  
  556. global shutdown_event, source, scheme
  557. shutdown_event = threading.Event()
  558.  
  559. signal.signal(signal.SIGINT, ctrl_c)
  560.  
  561. description = (
  562. 'Command line interface for testing internet bandwidth using '
  563. 'speedtest.net.\n'
  564. '------------------------------------------------------------'
  565. '--------------\n'
  566. 'https://github.com/sivel/speedtest-cli')
  567.  
  568. parser = ArgParser(description=description)
  569. # Give optparse.OptionParser an `add_argument` method for
  570. # compatibility with argparse.ArgumentParser
  571. try:
  572. parser.add_argument = parser.add_option
  573. except AttributeError:
  574. pass
  575. parser.add_argument('--bytes', dest='units', action='store_const',
  576. const=('byte', 1), default=('bit', 8),
  577. help='Display values in bytes instead of bits. Does '
  578. 'not affect the image generated by --share')
  579. parser.add_argument('--share', action='store_true',
  580. help='Generate and provide a URL to the speedtest.net '
  581. 'share results image')
  582. parser.add_argument('--simple', action='store_true',
  583. help='Suppress verbose output, only show basic '
  584. 'information')
  585. parser.add_argument('--list', action='store_true',
  586. help='Display a list of speedtest.net servers '
  587. 'sorted by distance')
  588. parser.add_argument('--server', help='Specify a server ID to test against')
  589. parser.add_argument('--mini', help='URL of the Speedtest Mini server')
  590. parser.add_argument('--source', help='Source IP address to bind to')
  591. parser.add_argument('--timeout', default=10, type=int,
  592. help='HTTP timeout in seconds. Default 10')
  593. parser.add_argument('--secure', action='store_true',
  594. help='Use HTTPS instead of HTTP when communicating '
  595. 'with speedtest.net operated servers')
  596. parser.add_argument('--version', action='store_true',
  597. help='Show the version number and exit')
  598.  
  599. options = parser.parse_args()
  600. if isinstance(options, tuple):
  601. args = options[0]
  602. else:
  603. args = options
  604. del options
  605.  
  606. # Print the version and exit
  607. if args.version:
  608. version()
  609.  
  610. socket.setdefaulttimeout(args.timeout)
  611.  
  612. # Pre-cache the user agent string
  613. build_user_agent()
  614.  
  615. # If specified bind to a specific IP address
  616. if args.source:
  617. source = args.source
  618. socket.socket = bound_socket
  619.  
  620. if args.secure:
  621. scheme = 'https'
  622.  
  623. if not args.simple:
  624. print_('Retrieving speedtest.net configuration...')
  625. try:
  626. config = getConfig()
  627. except URLError:
  628. print_('Cannot retrieve speedtest configuration')
  629. sys.exit(1)
  630.  
  631. if not args.simple:
  632. print_('Retrieving speedtest.net server list...')
  633. if args.list or args.server:
  634. servers = closestServers(config['client'], True)
  635. if args.list:
  636. serverList = []
  637. for server in servers:
  638. line = ('%(id)4s) %(sponsor)s (%(name)s, %(country)s) '
  639. '[%(d)0.2f km]' % server)
  640. serverList.append(line)
  641. print_('\n'.join(serverList).encode('utf-8', 'ignore'))
  642. sys.exit(0)
  643. else:
  644. servers = closestServers(config['client'])
  645.  
  646. if not args.simple:
  647. print_('Testing from %(isp)s (%(ip)s)...' % config['client'])
  648.  
  649. if args.server:
  650. try:
  651. best = getBestServer(filter(lambda x: x['id'] == args.server,
  652. servers))
  653. except IndexError:
  654. print_('Invalid server ID')
  655. sys.exit(1)
  656. elif args.mini:
  657. name, ext = os.path.splitext(args.mini)
  658. if ext:
  659. url = os.path.dirname(args.mini)
  660. else:
  661. url = args.mini
  662. urlparts = urlparse(url)
  663. try:
  664. request = build_request(args.mini)
  665. f = urlopen(request)
  666. except:
  667. print_('Invalid Speedtest Mini URL')
  668. sys.exit(1)
  669. else:
  670. text = f.read()
  671. f.close()
  672. extension = re.findall('upload_extension: "([^"]+)"', text.decode())
  673. if not extension:
  674. for ext in ['php', 'asp', 'aspx', 'jsp']:
  675. try:
  676. request = build_request('%s/speedtest/upload.%s' %
  677. (args.mini, ext))
  678. f = urlopen(request)
  679. except:
  680. pass
  681. else:
  682. data = f.read().strip()
  683. if (f.code == 200 and
  684. len(data.splitlines()) == 1 and
  685. re.match('size=[0-9]', data)):
  686. extension = [ext]
  687. break
  688. if not urlparts or not extension:
  689. print_('Please provide the full URL of your Speedtest Mini server')
  690. sys.exit(1)
  691. servers = [{
  692. 'sponsor': 'Speedtest Mini',
  693. 'name': urlparts[1],
  694. 'd': 0,
  695. 'url': '%s/speedtest/upload.%s' % (url.rstrip('/'), extension[0]),
  696. 'latency': 0,
  697. 'id': 0
  698. }]
  699. try:
  700. best = getBestServer(servers)
  701. except:
  702. best = servers[0]
  703. else:
  704. if not args.simple:
  705. print_('Selecting best server based on latency...')
  706. best = getBestServer(servers)
  707.  
  708. if not args.simple:
  709. print_(('Hosted by %(sponsor)s (%(name)s) [%(d)0.2f km]: '
  710. '%(latency)s ms' % best).encode('utf-8', 'ignore'))
  711. else:
  712. print_('Ping: %(latency)s ms' % best)
  713.  
  714. sizes = [350, 500, 750, 1000, 1500, 2000, 2500, 3000, 3500, 4000]
  715. urls = []
  716. for size in sizes:
  717. for i in range(0, 4):
  718. urls.append('%s/random%sx%s.jpg' %
  719. (os.path.dirname(best['url']), size, size))
  720. if not args.simple:
  721. print_('Testing download speed', end='')
  722. dlspeed = downloadSpeed(urls, args.simple)
  723. if not args.simple:
  724. print_()
  725. print_('Download: %0.2f M%s/s' %
  726. ((dlspeed / 1000 / 1000) * args.units[1], args.units[0]))
  727. sizesizes = [int(.25 * 1000 * 1000), int(.5 * 1000 * 1000)]
  728. sizes = []
  729. for size in sizesizes:
  730. for i in range(0, 25):
  731. sizes.append(size)
  732.  
  733.  
  734. ### DA added
  735.  
  736. downspeedy = ('%0.2f' %
  737. ((dlspeed / 1000 / 1000) * args.units[1]))
  738.  
  739. print downspeedy
  740.  
  741. mqttc.publish("internet/download", downspeedy, retain=True)
  742. ############
  743.  
  744. for size in sizesizes:
  745. for i in range(0, 25):
  746. sizes.append(size)
  747.  
  748. if not args.simple:
  749. print_('Testing upload speed', end='')
  750. ulspeed = uploadSpeed(best['url'], sizes, args.simple)
  751. if not args.simple:
  752. print_()
  753. print_('Upload: %0.2f M%s/s' %
  754. ((ulspeed / 1000 / 1000) * args.units[1], args.units[0]))
  755.  
  756. ### DA added
  757.  
  758. upspeedy = ('%0.2f' %
  759. ((ulspeed / 1000 / 1000) * args.units[1]))
  760. print upspeedy
  761. mqttc.publish("internet/upload", upspeedy, retain=True)
  762.  
  763. ############
  764.  
  765. if args.share and args.mini:
  766. print_('Cannot generate a speedtest.net share results image while '
  767. 'testing against a Speedtest Mini server')
  768. elif args.share:
  769. dlspeedk = int(round((dlspeed / 1000) * 8, 0))
  770. ping = int(round(best['latency'], 0))
  771. ulspeedk = int(round((ulspeed / 1000) * 8, 0))
  772.  
  773. # Build the request to send results back to speedtest.net
  774. # We use a list instead of a dict because the API expects parameters
  775. # in a certain order
  776. apiData = [
  777. 'download=%s' % dlspeedk,
  778. 'ping=%s' % ping,
  779. 'upload=%s' % ulspeedk,
  780. 'promo=',
  781. 'startmode=%s' % 'pingselect',
  782. 'recommendedserverid=%s' % best['id'],
  783. 'accuracy=%s' % 1,
  784. 'serverid=%s' % best['id'],
  785. 'hash=%s' % md5(('%s-%s-%s-%s' %
  786. (ping, ulspeedk, dlspeedk, '297aae72'))
  787. .encode()).hexdigest()]
  788.  
  789. headers = {'Referer': 'http://c.speedtest.net/flash/speedtest.swf'}
  790. request = build_request('://www.speedtest.net/api/api.php',
  791. data='&'.join(apiData).encode(),
  792. headers=headers)
  793. f, e = catch_request(request)
  794. if e:
  795. print_('Could not submit results to speedtest.net: %s' % e)
  796. sys.exit(1)
  797. response = f.read()
  798. code = f.code
  799. f.close()
  800.  
  801. if int(code) != 200:
  802. print_('Could not submit results to speedtest.net')
  803. sys.exit(1)
  804.  
  805. qsargs = parse_qs(response.decode())
  806. resultid = qsargs.get('resultid')
  807. if not resultid or len(resultid) != 1:
  808. print_('Could not submit results to speedtest.net')
  809. sys.exit(1)
  810.  
  811. print_('Share results: %s://www.speedtest.net/result/%s.png' %
  812. (scheme, resultid[0]))
  813.  
  814.  
  815. def main():
  816. try:
  817. speedtest()
  818. except KeyboardInterrupt:
  819. print_('\nCancelling...')
  820.  
  821.  
  822. if __name__ == '__main__':
  823. main()
  824.  
  825. # vim:ts=4:sw=4:expandtab
Advertisement
Add Comment
Please, Sign In to add comment