├── .gitignore ├── LICENSE ├── README.md ├── SI1145 ├── SI1145.py └── __init__.py ├── examples └── simpletest.py ├── ez_setup.py └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | dist/ 3 | *.egg-info 4 | *.pyc 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Joe Gutting 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Python_SI1145 2 | ============= 3 | 4 | Python library for accessing the SI1145 temperature sensor on a Raspberry Pi. 5 | 6 | Designed specifically to work with the Adafruit SI1145 sensors ----> https://www.adafruit.com/product/1777 7 | 8 | To install, download the library by clicking the download zip link to the right and unzip the archive somewhere on your Raspberry Pi. Then execute the following command in the directory of the library: 9 | 10 | sudo python setup.py install 11 | 12 | Make sure you have internet access on the device so it can download the required dependencies. 13 | 14 | See examples of usage in the examples folder. 15 | 16 | Please support Adafruit (though I have no connection to them) and open-source hardware by purchasing products from Adafruit! 17 | 18 | Written by Joe Gutting. MIT license, all text above must be included in any redistribution. 19 | 20 | Credit to Adafruit for their Arduino SI1145 library as well as their Adafruit GPIO I2C library. Also to Tony Dicola for his BMP python library which I used as a template. 21 | -------------------------------------------------------------------------------- /SI1145/SI1145.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | 4 | # Author: Joe Gutting 5 | # With use of Adafruit SI1145 library for Arduino, Adafruit_GPIO.I2C & BMP Library by Tony DiCola 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in 15 | # all copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | # THE SOFTWARE. 24 | 25 | import logging 26 | import time 27 | 28 | import Adafruit_GPIO.I2C as I2C 29 | 30 | # COMMANDS 31 | SI1145_PARAM_QUERY = 0x80 32 | SI1145_PARAM_SET = 0xA0 33 | SI1145_NOP = 0x0 34 | SI1145_RESET = 0x01 35 | SI1145_BUSADDR = 0x02 36 | SI1145_PS_FORCE = 0x05 37 | SI1145_ALS_FORCE = 0x06 38 | SI1145_PSALS_FORCE = 0x07 39 | SI1145_PS_PAUSE = 0x09 40 | SI1145_ALS_PAUSE = 0x0A 41 | SI1145_PSALS_PAUSE = 0xB 42 | SI1145_PS_AUTO = 0x0D 43 | SI1145_ALS_AUTO = 0x0E 44 | SI1145_PSALS_AUTO = 0x0F 45 | SI1145_GET_CAL = 0x12 46 | 47 | # Parameters 48 | SI1145_PARAM_I2CADDR = 0x00 49 | SI1145_PARAM_CHLIST = 0x01 50 | SI1145_PARAM_CHLIST_ENUV = 0x80 51 | SI1145_PARAM_CHLIST_ENAUX = 0x40 52 | SI1145_PARAM_CHLIST_ENALSIR = 0x20 53 | SI1145_PARAM_CHLIST_ENALSVIS = 0x10 54 | SI1145_PARAM_CHLIST_ENPS1 = 0x01 55 | SI1145_PARAM_CHLIST_ENPS2 = 0x02 56 | SI1145_PARAM_CHLIST_ENPS3 = 0x04 57 | 58 | SI1145_PARAM_PSLED12SEL = 0x02 59 | SI1145_PARAM_PSLED12SEL_PS2NONE = 0x00 60 | SI1145_PARAM_PSLED12SEL_PS2LED1 = 0x10 61 | SI1145_PARAM_PSLED12SEL_PS2LED2 = 0x20 62 | SI1145_PARAM_PSLED12SEL_PS2LED3 = 0x40 63 | SI1145_PARAM_PSLED12SEL_PS1NONE = 0x00 64 | SI1145_PARAM_PSLED12SEL_PS1LED1 = 0x01 65 | SI1145_PARAM_PSLED12SEL_PS1LED2 = 0x02 66 | SI1145_PARAM_PSLED12SEL_PS1LED3 = 0x04 67 | 68 | SI1145_PARAM_PSLED3SEL = 0x03 69 | SI1145_PARAM_PSENCODE = 0x05 70 | SI1145_PARAM_ALSENCODE = 0x06 71 | 72 | SI1145_PARAM_PS1ADCMUX = 0x07 73 | SI1145_PARAM_PS2ADCMUX = 0x08 74 | SI1145_PARAM_PS3ADCMUX = 0x09 75 | SI1145_PARAM_PSADCOUNTER = 0x0A 76 | SI1145_PARAM_PSADCGAIN = 0x0B 77 | SI1145_PARAM_PSADCMISC = 0x0C 78 | SI1145_PARAM_PSADCMISC_RANGE = 0x20 79 | SI1145_PARAM_PSADCMISC_PSMODE = 0x04 80 | 81 | SI1145_PARAM_ALSIRADCMUX = 0x0E 82 | SI1145_PARAM_AUXADCMUX = 0x0F 83 | 84 | SI1145_PARAM_ALSVISADCOUNTER = 0x10 85 | SI1145_PARAM_ALSVISADCGAIN = 0x11 86 | SI1145_PARAM_ALSVISADCMISC = 0x12 87 | SI1145_PARAM_ALSVISADCMISC_VISRANGE = 0x20 88 | 89 | SI1145_PARAM_ALSIRADCOUNTER = 0x1D 90 | SI1145_PARAM_ALSIRADCGAIN = 0x1E 91 | SI1145_PARAM_ALSIRADCMISC = 0x1F 92 | SI1145_PARAM_ALSIRADCMISC_RANGE = 0x20 93 | 94 | SI1145_PARAM_ADCCOUNTER_511CLK = 0x70 95 | 96 | SI1145_PARAM_ADCMUX_SMALLIR = 0x00 97 | SI1145_PARAM_ADCMUX_LARGEIR = 0x03 98 | 99 | 100 | 101 | # REGISTERS 102 | SI1145_REG_PARTID = 0x00 103 | SI1145_REG_REVID = 0x01 104 | SI1145_REG_SEQID = 0x02 105 | 106 | SI1145_REG_INTCFG = 0x03 107 | SI1145_REG_INTCFG_INTOE = 0x01 108 | SI1145_REG_INTCFG_INTMODE = 0x02 109 | 110 | SI1145_REG_IRQEN = 0x04 111 | SI1145_REG_IRQEN_ALSEVERYSAMPLE = 0x01 112 | SI1145_REG_IRQEN_PS1EVERYSAMPLE = 0x04 113 | SI1145_REG_IRQEN_PS2EVERYSAMPLE = 0x08 114 | SI1145_REG_IRQEN_PS3EVERYSAMPLE = 0x10 115 | 116 | 117 | SI1145_REG_IRQMODE1 = 0x05 118 | SI1145_REG_IRQMODE2 = 0x06 119 | 120 | SI1145_REG_HWKEY = 0x07 121 | SI1145_REG_MEASRATE0 = 0x08 122 | SI1145_REG_MEASRATE1 = 0x09 123 | SI1145_REG_PSRATE = 0x0A 124 | SI1145_REG_PSLED21 = 0x0F 125 | SI1145_REG_PSLED3 = 0x10 126 | SI1145_REG_UCOEFF0 = 0x13 127 | SI1145_REG_UCOEFF1 = 0x14 128 | SI1145_REG_UCOEFF2 = 0x15 129 | SI1145_REG_UCOEFF3 = 0x16 130 | SI1145_REG_PARAMWR = 0x17 131 | SI1145_REG_COMMAND = 0x18 132 | SI1145_REG_RESPONSE = 0x20 133 | SI1145_REG_IRQSTAT = 0x21 134 | SI1145_REG_IRQSTAT_ALS = 0x01 135 | 136 | SI1145_REG_ALSVISDATA0 = 0x22 137 | SI1145_REG_ALSVISDATA1 = 0x23 138 | SI1145_REG_ALSIRDATA0 = 0x24 139 | SI1145_REG_ALSIRDATA1 = 0x25 140 | SI1145_REG_PS1DATA0 = 0x26 141 | SI1145_REG_PS1DATA1 = 0x27 142 | SI1145_REG_PS2DATA0 = 0x28 143 | SI1145_REG_PS2DATA1 = 0x29 144 | SI1145_REG_PS3DATA0 = 0x2A 145 | SI1145_REG_PS3DATA1 = 0x2B 146 | SI1145_REG_UVINDEX0 = 0x2C 147 | SI1145_REG_UVINDEX1 = 0x2D 148 | SI1145_REG_PARAMRD = 0x2E 149 | SI1145_REG_CHIPSTAT = 0x30 150 | 151 | # I2C Address 152 | SI1145_ADDR = 0x60 153 | 154 | class SI1145(object): 155 | def __init__(self, address=SI1145_ADDR, busnum=I2C.get_default_bus()): 156 | 157 | self._logger = logging.getLogger('SI1145') 158 | 159 | # Create I2C device. 160 | self._device = I2C.Device(address, busnum) 161 | 162 | #reset device 163 | self._reset() 164 | 165 | # Load calibration values. 166 | self._load_calibration() 167 | 168 | # device reset 169 | def _reset(self): 170 | self._device.write8(SI1145_REG_MEASRATE0, 0) 171 | self._device.write8(SI1145_REG_MEASRATE1, 0) 172 | self._device.write8(SI1145_REG_IRQEN, 0) 173 | self._device.write8(SI1145_REG_IRQMODE1, 0) 174 | self._device.write8(SI1145_REG_IRQMODE2, 0) 175 | self._device.write8(SI1145_REG_INTCFG, 0) 176 | self._device.write8(SI1145_REG_IRQSTAT, 0xFF) 177 | 178 | self._device.write8(SI1145_REG_COMMAND, SI1145_RESET) 179 | time.sleep(.01) 180 | self._device.write8(SI1145_REG_HWKEY, 0x17) 181 | time.sleep(.01) 182 | 183 | # write Param 184 | def writeParam(self, p, v): 185 | self._device.write8(SI1145_REG_PARAMWR, v) 186 | self._device.write8(SI1145_REG_COMMAND, p | SI1145_PARAM_SET) 187 | paramVal = self._device.readU8(SI1145_REG_PARAMRD) 188 | return paramVal 189 | 190 | # load calibration to sensor 191 | def _load_calibration(self): 192 | # /***********************************/ 193 | # Enable UVindex measurement coefficients! 194 | self._device.write8(SI1145_REG_UCOEFF0, 0x29) 195 | self._device.write8(SI1145_REG_UCOEFF1, 0x89) 196 | self._device.write8(SI1145_REG_UCOEFF2, 0x02) 197 | self._device.write8(SI1145_REG_UCOEFF3, 0x00) 198 | 199 | # Enable UV sensor 200 | self.writeParam(SI1145_PARAM_CHLIST, SI1145_PARAM_CHLIST_ENUV | SI1145_PARAM_CHLIST_ENALSIR | SI1145_PARAM_CHLIST_ENALSVIS | SI1145_PARAM_CHLIST_ENPS1) 201 | 202 | # Enable interrupt on every sample 203 | self._device.write8(SI1145_REG_INTCFG, SI1145_REG_INTCFG_INTOE) 204 | self._device.write8(SI1145_REG_IRQEN, SI1145_REG_IRQEN_ALSEVERYSAMPLE) 205 | 206 | # /****************************** Prox Sense 1 */ 207 | 208 | # Program LED current 209 | self._device.write8(SI1145_REG_PSLED21, 0x03) # 20mA for LED 1 only 210 | self.writeParam(SI1145_PARAM_PS1ADCMUX, SI1145_PARAM_ADCMUX_LARGEIR) 211 | 212 | # Prox sensor #1 uses LED #1 213 | self.writeParam(SI1145_PARAM_PSLED12SEL, SI1145_PARAM_PSLED12SEL_PS1LED1) 214 | 215 | # Fastest clocks, clock div 1 216 | self.writeParam(SI1145_PARAM_PSADCGAIN, 0) 217 | 218 | # Take 511 clocks to measure 219 | self.writeParam(SI1145_PARAM_PSADCOUNTER, SI1145_PARAM_ADCCOUNTER_511CLK) 220 | 221 | # in prox mode, high range 222 | self.writeParam(SI1145_PARAM_PSADCMISC, SI1145_PARAM_PSADCMISC_RANGE | SI1145_PARAM_PSADCMISC_PSMODE) 223 | self.writeParam(SI1145_PARAM_ALSIRADCMUX, SI1145_PARAM_ADCMUX_SMALLIR) 224 | 225 | # Fastest clocks, clock div 1 226 | self.writeParam(SI1145_PARAM_ALSIRADCGAIN, 0) 227 | 228 | # Take 511 clocks to measure 229 | self.writeParam(SI1145_PARAM_ALSIRADCOUNTER, SI1145_PARAM_ADCCOUNTER_511CLK) 230 | 231 | # in high range mode 232 | self.writeParam(SI1145_PARAM_ALSIRADCMISC, SI1145_PARAM_ALSIRADCMISC_RANGE) 233 | 234 | # fastest clocks, clock div 1 235 | self.writeParam(SI1145_PARAM_ALSVISADCGAIN, 0) 236 | 237 | # Take 511 clocks to measure 238 | self.writeParam(SI1145_PARAM_ALSVISADCOUNTER, SI1145_PARAM_ADCCOUNTER_511CLK) 239 | 240 | # in high range mode (not normal signal) 241 | self.writeParam(SI1145_PARAM_ALSVISADCMISC, SI1145_PARAM_ALSVISADCMISC_VISRANGE) 242 | 243 | # measurement rate for auto 244 | self._device.write8(SI1145_REG_MEASRATE0, 0xFF) # 255 * 31.25uS = 8ms 245 | 246 | # auto run 247 | self._device.write8(SI1145_REG_COMMAND, SI1145_PSALS_AUTO) 248 | 249 | # returns the UV index * 100 (divide by 100 to get the index) 250 | def readUV(self): 251 | return self._device.readU16LE(0x2C) 252 | 253 | #returns visible + IR light levels 254 | def readVisible(self): 255 | return self._device.readU16LE(0x22) 256 | 257 | #returns IR light levels 258 | def readIR(self): 259 | return self._device.readU16LE(0x24) 260 | 261 | # Returns "Proximity" - assumes an IR LED is attached to LED 262 | def readProx(self): 263 | return self._device.readU16LE(0x26) 264 | 265 | -------------------------------------------------------------------------------- /SI1145/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/simpletest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Author: Joe Gutting 4 | # With use of Adafruit SI1145 library for Arduino, Adafruit_GPIO.I2C & BMP Library by Tony DiCola 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | 24 | # Can enable debug output by uncommenting: 25 | #import logging 26 | #logging.basicConfig(level=logging.DEBUG) 27 | 28 | import time 29 | import SI1145.SI1145 as SI1145 30 | 31 | 32 | # Default constructor will pick a default I2C bus. 33 | # 34 | # For the Raspberry Pi this means you should hook up to the only exposed I2C bus 35 | # from the main GPIO header and the library will figure out the bus number based 36 | # on the Pi's revision. 37 | # 38 | # For the Beaglebone Black the library will assume bus 1 by default, which is 39 | # exposed with I2C1_SCL = P9_17 and I2C1_SDA = P9_18 40 | # Header pinout: http://beagleboard.org/static/images/cape-headers-i2c.png 41 | # Configure the pins for I2C with these pins: 42 | # sudo config-pin p9.17 i2c 43 | # sudo config-pin p9.18 i2c 44 | 45 | sensor = SI1145.SI1145() 46 | 47 | print 'Press Cntrl + Z to cancel' 48 | 49 | while True: 50 | vis = sensor.readVisible() 51 | IR = sensor.readIR() 52 | UV = sensor.readUV() 53 | uvIndex = UV / 100.0 54 | print 'Vis: ' + str(vis) 55 | print 'IR: ' + str(IR) 56 | print 'UV Index: ' + str(uvIndex) 57 | 58 | time.sleep(3) 59 | 60 | -------------------------------------------------------------------------------- /ez_setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copied from Tony Dicola's BMP085 Python Library 3 | 4 | """Bootstrap setuptools installation 5 | 6 | To use setuptools in your package's setup.py, include this 7 | file in the same directory and add this to the top of your setup.py:: 8 | 9 | from ez_setup import use_setuptools 10 | use_setuptools() 11 | 12 | To require a specific version of setuptools, set a download 13 | mirror, or use an alternate download directory, simply supply 14 | the appropriate options to ``use_setuptools()``. 15 | 16 | This file can also be run as a script to install or upgrade setuptools. 17 | """ 18 | import os 19 | import shutil 20 | import sys 21 | import tempfile 22 | import zipfile 23 | import optparse 24 | import subprocess 25 | import platform 26 | import textwrap 27 | import contextlib 28 | 29 | from distutils import log 30 | 31 | try: 32 | from site import USER_SITE 33 | except ImportError: 34 | USER_SITE = None 35 | 36 | DEFAULT_VERSION = "3.5.1" 37 | DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" 38 | 39 | def _python_cmd(*args): 40 | """ 41 | Return True if the command succeeded. 42 | """ 43 | args = (sys.executable,) + args 44 | return subprocess.call(args) == 0 45 | 46 | 47 | def _install(archive_filename, install_args=()): 48 | with archive_context(archive_filename): 49 | # installing 50 | log.warn('Installing Setuptools') 51 | if not _python_cmd('setup.py', 'install', *install_args): 52 | log.warn('Something went wrong during the installation.') 53 | log.warn('See the error message above.') 54 | # exitcode will be 2 55 | return 2 56 | 57 | 58 | def _build_egg(egg, archive_filename, to_dir): 59 | with archive_context(archive_filename): 60 | # building an egg 61 | log.warn('Building a Setuptools egg in %s', to_dir) 62 | _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir) 63 | # returning the result 64 | log.warn(egg) 65 | if not os.path.exists(egg): 66 | raise IOError('Could not build the egg.') 67 | 68 | 69 | def get_zip_class(): 70 | """ 71 | Supplement ZipFile class to support context manager for Python 2.6 72 | """ 73 | class ContextualZipFile(zipfile.ZipFile): 74 | def __enter__(self): 75 | return self 76 | def __exit__(self, type, value, traceback): 77 | self.close 78 | return zipfile.ZipFile if hasattr(zipfile.ZipFile, '__exit__') else \ 79 | ContextualZipFile 80 | 81 | 82 | @contextlib.contextmanager 83 | def archive_context(filename): 84 | # extracting the archive 85 | tmpdir = tempfile.mkdtemp() 86 | log.warn('Extracting in %s', tmpdir) 87 | old_wd = os.getcwd() 88 | try: 89 | os.chdir(tmpdir) 90 | with get_zip_class()(filename) as archive: 91 | archive.extractall() 92 | 93 | # going in the directory 94 | subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0]) 95 | os.chdir(subdir) 96 | log.warn('Now working in %s', subdir) 97 | yield 98 | 99 | finally: 100 | os.chdir(old_wd) 101 | shutil.rmtree(tmpdir) 102 | 103 | 104 | def _do_download(version, download_base, to_dir, download_delay): 105 | egg = os.path.join(to_dir, 'setuptools-%s-py%d.%d.egg' 106 | % (version, sys.version_info[0], sys.version_info[1])) 107 | if not os.path.exists(egg): 108 | archive = download_setuptools(version, download_base, 109 | to_dir, download_delay) 110 | _build_egg(egg, archive, to_dir) 111 | sys.path.insert(0, egg) 112 | 113 | # Remove previously-imported pkg_resources if present (see 114 | # https://bitbucket.org/pypa/setuptools/pull-request/7/ for details). 115 | if 'pkg_resources' in sys.modules: 116 | del sys.modules['pkg_resources'] 117 | 118 | import setuptools 119 | setuptools.bootstrap_install_from = egg 120 | 121 | 122 | def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, 123 | to_dir=os.curdir, download_delay=15): 124 | to_dir = os.path.abspath(to_dir) 125 | rep_modules = 'pkg_resources', 'setuptools' 126 | imported = set(sys.modules).intersection(rep_modules) 127 | try: 128 | import pkg_resources 129 | except ImportError: 130 | return _do_download(version, download_base, to_dir, download_delay) 131 | try: 132 | pkg_resources.require("setuptools>=" + version) 133 | return 134 | except pkg_resources.DistributionNotFound: 135 | return _do_download(version, download_base, to_dir, download_delay) 136 | except pkg_resources.VersionConflict as VC_err: 137 | if imported: 138 | msg = textwrap.dedent(""" 139 | The required version of setuptools (>={version}) is not available, 140 | and can't be installed while this script is running. Please 141 | install a more recent version first, using 142 | 'easy_install -U setuptools'. 143 | 144 | (Currently using {VC_err.args[0]!r}) 145 | """).format(VC_err=VC_err, version=version) 146 | sys.stderr.write(msg) 147 | sys.exit(2) 148 | 149 | # otherwise, reload ok 150 | del pkg_resources, sys.modules['pkg_resources'] 151 | return _do_download(version, download_base, to_dir, download_delay) 152 | 153 | def _clean_check(cmd, target): 154 | """ 155 | Run the command to download target. If the command fails, clean up before 156 | re-raising the error. 157 | """ 158 | try: 159 | subprocess.check_call(cmd) 160 | except subprocess.CalledProcessError: 161 | if os.access(target, os.F_OK): 162 | os.unlink(target) 163 | raise 164 | 165 | def download_file_powershell(url, target): 166 | """ 167 | Download the file at url to target using Powershell (which will validate 168 | trust). Raise an exception if the command cannot complete. 169 | """ 170 | target = os.path.abspath(target) 171 | cmd = [ 172 | 'powershell', 173 | '-Command', 174 | "(new-object System.Net.WebClient).DownloadFile(%(url)r, %(target)r)" % vars(), 175 | ] 176 | _clean_check(cmd, target) 177 | 178 | def has_powershell(): 179 | if platform.system() != 'Windows': 180 | return False 181 | cmd = ['powershell', '-Command', 'echo test'] 182 | devnull = open(os.path.devnull, 'wb') 183 | try: 184 | try: 185 | subprocess.check_call(cmd, stdout=devnull, stderr=devnull) 186 | except Exception: 187 | return False 188 | finally: 189 | devnull.close() 190 | return True 191 | 192 | download_file_powershell.viable = has_powershell 193 | 194 | def download_file_curl(url, target): 195 | cmd = ['curl', url, '--silent', '--output', target] 196 | _clean_check(cmd, target) 197 | 198 | def has_curl(): 199 | cmd = ['curl', '--version'] 200 | devnull = open(os.path.devnull, 'wb') 201 | try: 202 | try: 203 | subprocess.check_call(cmd, stdout=devnull, stderr=devnull) 204 | except Exception: 205 | return False 206 | finally: 207 | devnull.close() 208 | return True 209 | 210 | download_file_curl.viable = has_curl 211 | 212 | def download_file_wget(url, target): 213 | cmd = ['wget', url, '--quiet', '--output-document', target] 214 | _clean_check(cmd, target) 215 | 216 | def has_wget(): 217 | cmd = ['wget', '--version'] 218 | devnull = open(os.path.devnull, 'wb') 219 | try: 220 | try: 221 | subprocess.check_call(cmd, stdout=devnull, stderr=devnull) 222 | except Exception: 223 | return False 224 | finally: 225 | devnull.close() 226 | return True 227 | 228 | download_file_wget.viable = has_wget 229 | 230 | def download_file_insecure(url, target): 231 | """ 232 | Use Python to download the file, even though it cannot authenticate the 233 | connection. 234 | """ 235 | try: 236 | from urllib.request import urlopen 237 | except ImportError: 238 | from urllib2 import urlopen 239 | src = dst = None 240 | try: 241 | src = urlopen(url) 242 | # Read/write all in one block, so we don't create a corrupt file 243 | # if the download is interrupted. 244 | data = src.read() 245 | dst = open(target, "wb") 246 | dst.write(data) 247 | finally: 248 | if src: 249 | src.close() 250 | if dst: 251 | dst.close() 252 | 253 | download_file_insecure.viable = lambda: True 254 | 255 | def get_best_downloader(): 256 | downloaders = [ 257 | download_file_powershell, 258 | download_file_curl, 259 | download_file_wget, 260 | download_file_insecure, 261 | ] 262 | 263 | for dl in downloaders: 264 | if dl.viable(): 265 | return dl 266 | 267 | def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, 268 | to_dir=os.curdir, delay=15, downloader_factory=get_best_downloader): 269 | """ 270 | Download setuptools from a specified location and return its filename 271 | 272 | `version` should be a valid setuptools version number that is available 273 | as an egg for download under the `download_base` URL (which should end 274 | with a '/'). `to_dir` is the directory where the egg will be downloaded. 275 | `delay` is the number of seconds to pause before an actual download 276 | attempt. 277 | 278 | ``downloader_factory`` should be a function taking no arguments and 279 | returning a function for downloading a URL to a target. 280 | """ 281 | # making sure we use the absolute path 282 | to_dir = os.path.abspath(to_dir) 283 | zip_name = "setuptools-%s.zip" % version 284 | url = download_base + zip_name 285 | saveto = os.path.join(to_dir, zip_name) 286 | if not os.path.exists(saveto): # Avoid repeated downloads 287 | log.warn("Downloading %s", url) 288 | downloader = downloader_factory() 289 | downloader(url, saveto) 290 | return os.path.realpath(saveto) 291 | 292 | def _build_install_args(options): 293 | """ 294 | Build the arguments to 'python setup.py install' on the setuptools package 295 | """ 296 | return ['--user'] if options.user_install else [] 297 | 298 | def _parse_args(): 299 | """ 300 | Parse the command line for options 301 | """ 302 | parser = optparse.OptionParser() 303 | parser.add_option( 304 | '--user', dest='user_install', action='store_true', default=False, 305 | help='install in user site package (requires Python 2.6 or later)') 306 | parser.add_option( 307 | '--download-base', dest='download_base', metavar="URL", 308 | default=DEFAULT_URL, 309 | help='alternative URL from where to download the setuptools package') 310 | parser.add_option( 311 | '--insecure', dest='downloader_factory', action='store_const', 312 | const=lambda: download_file_insecure, default=get_best_downloader, 313 | help='Use internal, non-validating downloader' 314 | ) 315 | parser.add_option( 316 | '--version', help="Specify which version to download", 317 | default=DEFAULT_VERSION, 318 | ) 319 | options, args = parser.parse_args() 320 | # positional arguments are ignored 321 | return options 322 | 323 | def main(): 324 | """Install or upgrade setuptools and EasyInstall""" 325 | options = _parse_args() 326 | archive = download_setuptools( 327 | version=options.version, 328 | download_base=options.download_base, 329 | downloader_factory=options.downloader_factory, 330 | ) 331 | return _install(archive, _build_install_args(options)) 332 | 333 | if __name__ == '__main__': 334 | sys.exit(main()) 335 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from ez_setup import use_setuptools 2 | use_setuptools() 3 | from setuptools import setup, find_packages 4 | 5 | setup(name = 'SI1145', 6 | version = '1.0.0', 7 | author = 'Joe Gutting', 8 | author_email = 'gutting@gmail.com', 9 | description = 'Library for accessing the SI1145 UV sensor on a Raspberry Pi. Uses Adafruit GPIO I2C. Credit to Tony Dicola as used his BMP library. Also credit to Adafruit for SI1145 Arduino library', 10 | license = 'MIT', 11 | url = 'https://github.com/THP-JOE/Python_SI1145.git', 12 | dependency_links = ['https://github.com/adafruit/Adafruit_Python_GPIO/tarball/master#egg=Adafruit-GPIO-0.2.0'], 13 | install_requires = ['Adafruit-GPIO>=0.2.0'], 14 | packages = find_packages()) 15 | --------------------------------------------------------------------------------