gate: add 2nd. gate
Signed-off-by: Thomas Klaehn <thomas.klaehn@u-blox.com>
This commit is contained in:
parent
a5205cfbcb
commit
35d1aa796c
@ -1,27 +0,0 @@
|
||||
before_script:
|
||||
- "echo $CI_BUILD_ID"
|
||||
- "echo $CI_BUILD_REF_NAME"
|
||||
|
||||
stages:
|
||||
- test
|
||||
- release
|
||||
|
||||
tests:
|
||||
stage: test
|
||||
script:
|
||||
- "python scripts/pylint_wrapper.py -s gate_guard -s tests"
|
||||
- "nosetests --with-coverage --cover-package=gate_guard --cover-xml"
|
||||
- "nosetests --with-xunit tests/unittests/"
|
||||
- "sonar-runner"
|
||||
|
||||
releases:
|
||||
stage: release
|
||||
script:
|
||||
- "python scripts/create_release_script.py"
|
||||
- "python setup.py sdist"
|
||||
- "scripts/deploy_release.sh"
|
||||
only:
|
||||
- /^[0-9]{1,}.[0-9]{1,}.[0-9]{1,}$/
|
||||
except:
|
||||
- branches
|
||||
|
@ -9,7 +9,6 @@ import socket
|
||||
import ssl
|
||||
import time
|
||||
import paho.mqtt.client as mqtt
|
||||
import scipy.stats
|
||||
import gate_guard.data_buffer
|
||||
import gate_guard.light_sensor
|
||||
import gate_guard.engine
|
||||
@ -17,11 +16,14 @@ import gate_guard.power_sensor
|
||||
|
||||
STATE_INIT_1 = "init_1"
|
||||
STATE_INIT_2 = "init_2"
|
||||
|
||||
STATE_INIT_3 = "init_3"
|
||||
STATE_INIT_4 = "init_4"
|
||||
STATE_OPENED = "open"
|
||||
STATE_CLOSED = "close"
|
||||
STATE_OPENING = "opening"
|
||||
STATE_CLOSING = "closing"
|
||||
STATE_OPENING_1 = "opening_1"
|
||||
STATE_OPENING_2 = "opening_2"
|
||||
STATE_CLOSING_1 = "closing_1"
|
||||
STATE_CLOSING_2 = "closing_2"
|
||||
|
||||
LIGHT_READ_DELAY_S = 30
|
||||
LIGHT_CONSECUTIVE_READS = 10
|
||||
@ -42,33 +44,63 @@ POWER_CONSECUTIVE_READS = 10
|
||||
|
||||
SLOPE_COUNT = 10
|
||||
SLOPE_CNT_MIN = 2
|
||||
MAX_POWER = 500.0
|
||||
MAX_POWER_1 = 450.0
|
||||
MAX_POWER_2 = 300.0
|
||||
ENGINE_1_PIN_1 = 13
|
||||
ENGINE_1_PIN_2 = 19
|
||||
ENGINE_2_PIN_1 = 5
|
||||
ENGINE_2_PIN_2 = 6
|
||||
|
||||
def check_to_open(light_avg):
|
||||
'''Check if gate needs to be opened.'''
|
||||
ret = False
|
||||
current_date = datetime.datetime.now()
|
||||
if (current_date.hour >= 8) and (light_avg > LIGHT_LX_THRESHOLD):
|
||||
ret = True
|
||||
return ret
|
||||
|
||||
def check_to_close(light_avg):
|
||||
'''Check if gate needs to be closed.'''
|
||||
ret = False
|
||||
current_date = datetime.datetime.now()
|
||||
if (current_date.hour >= 16) and (light_avg <= LIGHT_LX_THRESHOLD):
|
||||
ret = True
|
||||
return ret
|
||||
|
||||
|
||||
class Gate(object):
|
||||
'''Main class of the chickenhouse gates.'''
|
||||
def __init__(self):
|
||||
self.__state_handler = {STATE_INIT_1:self.__init1_handler, \
|
||||
STATE_INIT_2:self.__init2_handler, \
|
||||
STATE_INIT_3:self.__init3_handler, \
|
||||
STATE_INIT_4:self.__init4_handler, \
|
||||
STATE_OPENED:self.__opened_handler, \
|
||||
STATE_CLOSED:self.__closed_handler, \
|
||||
STATE_OPENING:self.__opening_handler, \
|
||||
STATE_CLOSING:self.__closing_handler}
|
||||
STATE_OPENING_1:self.__opening_1_handler, \
|
||||
STATE_OPENING_2:self.__opening_2_handler, \
|
||||
STATE_CLOSING_1:self.__closing_1_handler, \
|
||||
STATE_CLOSING_2:self.__closing_2_handler}
|
||||
self.__next_state = STATE_INIT_1
|
||||
self.__last_state = STATE_OPENED
|
||||
self.__light_sensor = gate_guard.light_sensor.LightSensor(
|
||||
LIGHT_SENSOR_I2C_BUS, LIGHT_SENSOR_I2C_ADDRESS)
|
||||
self.__light_data = gate_guard.data_buffer.DataBuffer(
|
||||
LIGHT_CONSECUTIVE_READS)
|
||||
self.__engine = gate_guard.engine.Engine(gpio_1=13, gpio_2=19)
|
||||
self.__engine_1 = gate_guard.engine.Engine(gpio_1=ENGINE_1_PIN_1, gpio_2=ENGINE_1_PIN_2)
|
||||
self.__engine_2 = gate_guard.engine.Engine(gpio_1=ENGINE_2_PIN_1, gpio_2=ENGINE_2_PIN_2)
|
||||
self.__power_sensor = gate_guard.power_sensor.PowerSensor(
|
||||
POWER_SENSOR_I2C_BUS, POWER_SENSOR_I2C_ADDRESS)
|
||||
self.__power_data = gate_guard.data_buffer.DataBuffer(POWER_CONSECUTIVE_READS)
|
||||
self.__light_read_timeout = 0
|
||||
self.__down_run_time = 0
|
||||
self.__down_run_time_1 = 0
|
||||
self.__down_run_time_2 = 0
|
||||
self.__gate_run_time = 0
|
||||
self.__client = mqtt.Client()
|
||||
self.__client.tls_set(MQTT_CERTS)
|
||||
|
||||
def poll(self):
|
||||
'''Poll function of the state machine.'''
|
||||
current_time = time.time()
|
||||
if current_time >= self.__light_read_timeout:
|
||||
self.__light_read_timeout = current_time + LIGHT_READ_DELAY_S
|
||||
@ -94,7 +126,7 @@ class Gate(object):
|
||||
def __init1_handler(self, _):
|
||||
next_state = self.__next_state
|
||||
if self.__is_transition():
|
||||
self.__engine.down()
|
||||
self.__engine_1.down()
|
||||
# workaround for high power after starting engine
|
||||
time.sleep(1)
|
||||
msg = str(time.time()) + " Initialization"
|
||||
@ -106,53 +138,74 @@ class Gate(object):
|
||||
except (ValueError, TypeError, socket.error, ssl.CertificateError):
|
||||
logging.info('unable to publish to mqtt')
|
||||
pwr = self.__power_sensor.power_mw()
|
||||
logging.debug('pwr: ' + str(pwr) + ' mW')
|
||||
if pwr > MAX_POWER:
|
||||
msg = 'e1: {} mW'.format(pwr)
|
||||
logging.debug(msg)
|
||||
if pwr > MAX_POWER_1:
|
||||
next_state = STATE_INIT_2
|
||||
self.__update_state(next_state)
|
||||
|
||||
def __init2_handler(self, _):
|
||||
next_state = self.__next_state
|
||||
if self.__is_transition():
|
||||
self.__engine.up()
|
||||
self.__down_run_time = time.time()
|
||||
self.__engine_1.up()
|
||||
self.__down_run_time_1 = time.time()
|
||||
pwr = self.__power_sensor.power_mw()
|
||||
logging.debug('pwr: ' + str(pwr) + ' mW')
|
||||
msg = 'e1: {} mW'.format(pwr)
|
||||
logging.debug(msg)
|
||||
|
||||
if pwr > MAX_POWER:
|
||||
self.__down_run_time = (time.time() - self.__down_run_time) / 2
|
||||
logging.info('calculated down time: ' + str(self.__down_run_time) + ' s')
|
||||
if self.__down_run_time > 30:
|
||||
next_state = STATE_CLOSING
|
||||
if pwr > MAX_POWER_1:
|
||||
self.__down_run_time_1 = (time.time() - self.__down_run_time_1) / 2
|
||||
msg = 'calculated down time for engine 1: {} s'.format(self.__down_run_time_1)
|
||||
logging.info(msg)
|
||||
if self.__down_run_time_1 > 30:
|
||||
next_state = STATE_INIT_3
|
||||
else:
|
||||
logging.info("That's not very relaistic. Another try...")
|
||||
next_state = STATE_INIT_1
|
||||
self.__update_state(next_state)
|
||||
|
||||
def __check_to_open(self, light_avg):
|
||||
ret = False
|
||||
current_date = datetime.datetime.now()
|
||||
try:
|
||||
if (current_date.hour >= 8) and (light_avg > LIGHT_LX_THRESHOLD):
|
||||
ret = True
|
||||
except Exception as e:
|
||||
logging.error("{}".format(e))
|
||||
return ret
|
||||
def __init3_handler(self, _):
|
||||
next_state = self.__next_state
|
||||
if self.__is_transition():
|
||||
self.__engine_1.down()
|
||||
time.sleep(1)
|
||||
self.__engine_1.stop()
|
||||
self.__engine_2.down()
|
||||
# workaround for high power after starting engine
|
||||
time.sleep(1)
|
||||
pwr = self.__power_sensor.power_mw()
|
||||
msg = 'e2: {} mW'.format(pwr)
|
||||
logging.debug(msg)
|
||||
if pwr > MAX_POWER_2:
|
||||
next_state = STATE_INIT_4
|
||||
self.__update_state(next_state)
|
||||
|
||||
def __check_to_close(self, light_avg):
|
||||
ret = False
|
||||
if (light_avg != None) and (light_avg <= LIGHT_LX_THRESHOLD):
|
||||
current_date = datetime.datetime.now()
|
||||
if (current_date.hour >= 16) and (current_date.minute >= 0):
|
||||
ret = True
|
||||
return ret
|
||||
def __init4_handler(self, _):
|
||||
next_state = self.__next_state
|
||||
if self.__is_transition():
|
||||
self.__engine_2.up()
|
||||
self.__down_run_time_2 = time.time()
|
||||
pwr = self.__power_sensor.power_mw()
|
||||
msg = 'e2: {} mW'.format(pwr)
|
||||
logging.debug(msg)
|
||||
|
||||
if pwr > MAX_POWER_2:
|
||||
self.__down_run_time_2 = (time.time() - self.__down_run_time_2) / 2
|
||||
msg = 'calculated down time for engine 2: {} s'.format(self.__down_run_time_2)
|
||||
logging.info(msg)
|
||||
if self.__down_run_time_2 > 30:
|
||||
next_state = STATE_OPENED
|
||||
else:
|
||||
logging.info("That's not very relaistic. Another try...")
|
||||
next_state = STATE_INIT_3
|
||||
self.__update_state(next_state)
|
||||
|
||||
def __opened_handler(self, light_avg):
|
||||
next_state = self.__next_state
|
||||
if self.__is_transition():
|
||||
self.__engine.down()
|
||||
self.__engine_2.down()
|
||||
time.sleep(1)
|
||||
self.__engine.stop()
|
||||
self.__engine_2.stop()
|
||||
msg = str(time.time()) + " Opened"
|
||||
try:
|
||||
self.__client.connect(MQTT_HOST, MQTT_PORT)
|
||||
@ -161,14 +214,14 @@ class Gate(object):
|
||||
self.__client.loop_stop()
|
||||
except (ValueError, TypeError, socket.error, ssl.CertificateError):
|
||||
logging.info('unable to publish to mqtt')
|
||||
if self.__check_to_close(light_avg) is True:
|
||||
next_state = STATE_CLOSING
|
||||
if check_to_close(light_avg) is True:
|
||||
next_state = STATE_CLOSING_1
|
||||
self.__update_state(next_state)
|
||||
|
||||
def __closed_handler(self, light_avg):
|
||||
next_state = self.__next_state
|
||||
if self.__is_transition():
|
||||
self.__engine.stop()
|
||||
self.__engine_2.stop()
|
||||
msg = str(time.time()) + " Closed"
|
||||
try:
|
||||
self.__client.connect(MQTT_HOST, MQTT_PORT)
|
||||
@ -177,15 +230,15 @@ class Gate(object):
|
||||
self.__client.loop_stop()
|
||||
except (ValueError, TypeError, socket.error, ssl.CertificateError):
|
||||
logging.info('unable to publish to mqtt')
|
||||
if self.__check_to_open(light_avg) is True:
|
||||
next_state = STATE_OPENING
|
||||
if check_to_open(light_avg) is True:
|
||||
next_state = STATE_OPENING_1
|
||||
self.__update_state(next_state)
|
||||
|
||||
def __opening_handler(self, light_avg):
|
||||
def __opening_1_handler(self, light_avg):
|
||||
next_state = self.__next_state
|
||||
if self.__is_transition():
|
||||
self.__engine.up()
|
||||
msg = str(time.time()) + " Opening " + str(light_avg) + " lx"
|
||||
self.__engine_1.up()
|
||||
msg = str(time.time()) + " Opening" + str(light_avg) + " lx"
|
||||
try:
|
||||
self.__client.connect(MQTT_HOST, MQTT_PORT)
|
||||
self.__client.loop_start()
|
||||
@ -199,17 +252,41 @@ class Gate(object):
|
||||
time.sleep(1)
|
||||
|
||||
pwr = self.__power_sensor.power_mw()
|
||||
logging.debug('pwr - abs: ' + str(pwr) + ' mW\tavg: ' + str(self.__power_data.average()) + ' mW')
|
||||
if pwr > MAX_POWER:
|
||||
deviation = abs(time.time() - self.__gate_run_time - self.__down_run_time)
|
||||
logging.info('runtime deviation: ' + str(deviation))
|
||||
msg = 'e1 - abs: {} mW\tavg: {} mW'.format(pwr, self.__power_data.average())
|
||||
logging.debug(msg)
|
||||
if pwr > MAX_POWER_1:
|
||||
deviation = abs(time.time() - self.__gate_run_time - self.__down_run_time_1)
|
||||
msg = 'runtime deviation of engine 1: {} s'.format(deviation)
|
||||
logging.info(msg)
|
||||
next_state = STATE_OPENING_2
|
||||
self.__update_state(next_state)
|
||||
|
||||
def __opening_2_handler(self, _):
|
||||
next_state = self.__next_state
|
||||
if self.__is_transition():
|
||||
self.__engine_1.down()
|
||||
time.sleep(1)
|
||||
self.__engine_1.stop()
|
||||
self.__engine_2.up()
|
||||
self.__gate_run_time = time.time()
|
||||
|
||||
# workaround for high power after starting engine
|
||||
time.sleep(1)
|
||||
|
||||
pwr = self.__power_sensor.power_mw()
|
||||
msg = 'e2 - abs: {} mW\tavg: {} mW'.format(pwr, self.__power_data.average())
|
||||
logging.debug(msg)
|
||||
if pwr > MAX_POWER_2:
|
||||
deviation = abs(time.time() - self.__gate_run_time - self.__down_run_time_2)
|
||||
msg = 'runtime deviation: {}'.format(deviation)
|
||||
logging.info(msg)
|
||||
next_state = STATE_OPENED
|
||||
self.__update_state(next_state)
|
||||
|
||||
def __closing_handler(self, light_avg):
|
||||
def __closing_1_handler(self, light_avg):
|
||||
next_state = self.__next_state
|
||||
if self.__is_transition():
|
||||
self.__engine.down()
|
||||
self.__engine_1.down()
|
||||
msg = str(time.time()) + " Closing " + str(light_avg) + " lx"
|
||||
try:
|
||||
self.__client.connect(MQTT_HOST, MQTT_PORT)
|
||||
@ -224,13 +301,39 @@ class Gate(object):
|
||||
time.sleep(1)
|
||||
|
||||
pwr = self.__power_sensor.power_mw()
|
||||
logging.debug('pwr: ' + str(pwr) + ' mW')
|
||||
msg = 'e1: {} mW'.format(pwr)
|
||||
logging.debug(msg)
|
||||
opening_time = time.time() - self.__gate_run_time
|
||||
if opening_time > self.__down_run_time:
|
||||
logging.info("actual running time bigger than calculated (" + str(opening_time) + " vs. " + str(self.__down_run_time) + ").")
|
||||
next_state = STATE_CLOSED
|
||||
if pwr > MAX_POWER:
|
||||
self.__engine.stop()
|
||||
if opening_time > self.__down_run_time_1:
|
||||
msg = "Run time of gate 1 is bigger than calculated ({} vs. {}).".format(
|
||||
opening_time, self.__down_run_time_1)
|
||||
logging.info(msg)
|
||||
next_state = STATE_CLOSING_2
|
||||
if pwr > MAX_POWER_1:
|
||||
self.__engine_1.stop()
|
||||
next_state = STATE_INIT_1
|
||||
self.__update_state(next_state)
|
||||
|
||||
def __closing_2_handler(self, _):
|
||||
next_state = self.__next_state
|
||||
if self.__is_transition():
|
||||
self.__engine_1.stop()
|
||||
self.__engine_2.down()
|
||||
self.__gate_run_time = time.time()
|
||||
|
||||
# workaround for high power after starting engine
|
||||
time.sleep(1)
|
||||
|
||||
pwr = self.__power_sensor.power_mw()
|
||||
msg = 'e2: {} mW'.format(pwr)
|
||||
logging.debug(msg)
|
||||
opening_time = time.time() - self.__gate_run_time
|
||||
if opening_time > self.__down_run_time_2:
|
||||
msg = "Run time of gate 1 is bigger than calculated ({} vs. {}).".format(
|
||||
opening_time, self.__down_run_time_2)
|
||||
logging.info(msg)
|
||||
next_state = STATE_CLOSED
|
||||
if pwr > MAX_POWER_2:
|
||||
self.__engine_2.stop()
|
||||
next_state = STATE_INIT_1
|
||||
self.__update_state(next_state)
|
||||
|
@ -1,64 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
'''
|
||||
Created on Mar 13, 2017
|
||||
|
||||
@author: tkl
|
||||
'''
|
||||
import os
|
||||
import sys
|
||||
|
||||
DAEMON_START_SCRIPT_SRC = 'gate_guard.service'
|
||||
DAEMON_START_SCRIPT_DST = '/lib/systemd/system/' + DAEMON_START_SCRIPT_SRC
|
||||
|
||||
def main(_):
|
||||
project_version = ''
|
||||
project_name = ''
|
||||
project_namespace = ''
|
||||
if os.environ.has_key('CI_BUILD_TAG'):
|
||||
project_version = str(os.environ.get('CI_BUILD_TAG')).strip()
|
||||
# else:
|
||||
# return -1
|
||||
|
||||
if os.environ.has_key('CI_PROJECT_NAME'):
|
||||
project_name = str(os.environ.get('CI_PROJECT_NAME')).strip()
|
||||
# else:
|
||||
# return -1
|
||||
|
||||
if os.environ.has_key('CI_PROJECT_NAMESPACE'):
|
||||
project_namespace = str(os.environ.get('CI_PROJECT_NAMESPACE')).strip()
|
||||
# else:
|
||||
# return -1
|
||||
|
||||
setup_str = ' setup(name=\'' + project_name + '\', '
|
||||
setup_str += 'version=\'' + project_version + '\', '
|
||||
setup_str += 'author=\'tkl\', '
|
||||
setup_str += 'author_email=\'tkl@blackfinn.de\', '
|
||||
setup_str += 'url=\'https://files.blackfinn.de/' + project_namespace + \
|
||||
'/' + project_name + '\', '
|
||||
setup_str += 'packages=[\'gate_guard\']'
|
||||
setup_str_sdist = setup_str + ', scripts=[\'' + DAEMON_START_SCRIPT_SRC + '\'])\n'
|
||||
setup_str += ')\n'
|
||||
|
||||
handle = open('setup.py', 'w')
|
||||
handle.write('#!/usr/bin/env python\n')
|
||||
handle.write('from distutils.core import setup\n')
|
||||
handle.write('import shutil\n')
|
||||
handle.write('import os\n')
|
||||
handle.write('import stat\n')
|
||||
handle.write('import sys\n\n')
|
||||
handle.write('if sys.argv[1] == \'install\':\n')
|
||||
handle.write(' shutil.copyfile(\'' + DAEMON_START_SCRIPT_SRC + \
|
||||
'\', \'' + DAEMON_START_SCRIPT_DST + '\')\n')
|
||||
handle.write(' os.chmod(\'' + DAEMON_START_SCRIPT_DST + \
|
||||
'\', stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)\n')
|
||||
handle.write(setup_str)
|
||||
handle.write('elif sys.argv[1] == \'sdist\':\n')
|
||||
handle.write(setup_str_sdist)
|
||||
handle.write('\n')
|
||||
|
||||
handle.close()
|
||||
|
||||
return 0
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main(sys.argv[1:]))
|
@ -1,20 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -x
|
||||
|
||||
if [ -z ${CI_BUILD_TAG+x} ]; then
|
||||
echo "Tag name not found"
|
||||
exit 1;
|
||||
fi
|
||||
if [ -z ${CI_PROJECT_NAME+x} ]; then
|
||||
echo "Project name not found"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
delim="-"
|
||||
file_ext=".tar.gz"
|
||||
file=$CI_PROJECT_NAME$delim$CI_BUILD_TAG$file_ext
|
||||
current_dir=`pwd`
|
||||
release_dir="/dist/"
|
||||
release_file=$current_dir$release_dir$file
|
||||
|
||||
smbclient //proxy/files 4738tax -U tkl -c "mkdir python ; cd python ; mkdir $CI_PROJECT_NAME ; cd $CI_PROJECT_NAME ; put $release_file $file"
|
@ -1,26 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
'''
|
||||
Created on Feb 11, 2017
|
||||
|
||||
@author: tkl
|
||||
'''
|
||||
import os
|
||||
import sys
|
||||
import getopt
|
||||
|
||||
def main(argv):
|
||||
options, _ = getopt.getopt(argv, "s:", ["source="])
|
||||
source_list = []
|
||||
for opt, args in options:
|
||||
if opt in ("-s", "--source"):
|
||||
source_list.append(args)
|
||||
|
||||
source_str = ""
|
||||
for source in source_list:
|
||||
source_str += source + " "
|
||||
|
||||
os.system("pylint " + source_str + " -r n --msg-template=\"{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}\" > pylint.txt")
|
||||
return 0
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main(sys.argv[1:]))
|
24
setup.py
Normal file
24
setup.py
Normal file
@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env python
|
||||
from distutils.core import setup
|
||||
import shutil
|
||||
import os
|
||||
import stat
|
||||
import sys
|
||||
|
||||
NAME = 'chickenhouse'
|
||||
VERSION = '1.0.0'
|
||||
AUTHOR = 'tkl'
|
||||
EMAIL = 'tkl@blackfinn.de'
|
||||
URL = 'https://git.blackfinn.de/python/chickenhouse'
|
||||
PACKAGES = ['gate_guard']
|
||||
SCRIPTS = ['chickenhouse.service']
|
||||
|
||||
if sys.argv[1] == 'install':
|
||||
shutil.copyfile('chickenhouse.service', '/lib/systemd/system/chickenhouse.service')
|
||||
os.chmod('/lib/systemd/system/chickenhouse.service',
|
||||
stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
|
||||
setup(name=NAME, version=VERSION, author=AUTHOR, author_email=EMAIL,
|
||||
url=URL, packages=PACKAGES)
|
||||
elif sys.argv[1] == 'sdist':
|
||||
setup(name=NAME, version=VERSION, author=AUTHOR, author_email=EMAIL,
|
||||
url=URL, packages=PACKAGES, scripts=SCRIPTS)
|
@ -1,11 +0,0 @@
|
||||
sonar.projectKey=chickenhouse:python
|
||||
sonar.projectName=chickenhouse:python
|
||||
sonar.projectVersion=1.0
|
||||
sonar.host.url=http://sonarqube:9000
|
||||
sonar.sources=gate_guard
|
||||
sonar.tests=tests/unittests
|
||||
sonar.language=py
|
||||
sonar.sourceEncoding=UTF-8
|
||||
sonar.python.xunit.reportPath=nosetests.xml
|
||||
sonar.python.coverage.reportPath=coverage.xml
|
||||
sonar.python.pylint.reportPath=pylint.txt
|
Loading…
Reference in New Issue
Block a user