<file_sep>from flask import Flask
import subprocess
from flask import jsonify
#from squid_py.ddo.metadata import Metadata
#from squid_py.ocean import Ocean
#from squid_py.config import Config
from smbus import SMBus
# Import basic packages
import io
import logging
import os
import glob
import warnings

warnings.filterwarnings('ignore')

from time import gmtime, strftime


# Imports the Google Cloud client library
from google.cloud import vision
from google.cloud.vision import types

# Instantiates a client
client = vision.ImageAnnotatorClient()

# Path storing Pi camera photos
img_path = './images'


# Classification using Google Vision API
def proccess_picture():
    all_results = list()
    for img in os.listdir(img_path):
        if img.endswith('.jpg'):
            image = os.path.join(img_path, img)
            logging.info(image)

            with io.open(image, 'rb') as image_file:
                content = image_file.read()

                image = types.Image(content=content)

                response = client.label_detection(image=image)
                labels = response.label_annotations
                logging.info(strftime('%Y-%m-%d %H:%M:%S', gmtime()))
                logging.info('Labels:')
                result = []
                for label in labels:
                    logging.info(label)
                    result.append(label.description)
        all_results.append(result)
    return all_results


app = Flask(__name__)
bus = SMBus(1)
#ocean = Ocean(Config(filename='config.ini'))


@app.route("/api/status", methods=['GET'])
def status():
    return "status"


@app.route("/api/snap", methods=['GET'])
def snap():
    #subprocess.call('flask_app/scripts/take_photos.sh')
    #subprocess.call('/home/pi/git/pines-and-electronics/flask_app/scripts/take_photos.sh')
    this_cmd = "raspistill -t 10000 -tl 2000 -o /home/pi/git/pines-and-electronics/flask_app/images/image%04d.jpg"
    #this_cmd = "raspistill -o cam.jpg"
    #this_cmd = "ls"
    subprocess.call(this_cmd, shell=True)
    print("Ran", this_cmd)
    return 'snap!' + this_cmd


@app.route("/api/register", methods=['GET'])
def register():
    label_list = proccess_picture()

    summary = list()
    for i, label in enumerate(label_list):
        print(i, label)
        summary.append("|".join(label))
    #metadata =Metadata.get_example()
    #metadata['base']['tags'] = labels
    #ddo = ocean.assets.create(metadata, ocean.accounts._accounts[0])
    #return ddo.did
    return " *** ".join(summary)


@app.route("/api/snapshot", methods=['GET'])
def snapshot():
    return "snapshot"


@app.route("/api/linear", methods=['POST'])
def linear():
    bus.write_byte(8, ord("S"))
    return "linear"

@app.route("/api/start", methods=['GET'])
def start():
    bus.write_byte(8, ord("S"))
    return "START"

@app.route("/api/stop", methods=['GET'])
def stop():
    bus.write_byte(8, ord("s"))
    return "STOP"

@app.route("/api/steer", methods=['POST'])
def steer():
    bus.write_byte(9, ord('x'))
    return "steer"


# def publish_asset():
#     return ocean.assets.create(Metadata.get_example())


if __name__ == "__main__":
    app.run(port=3333)
<file_sep>#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""The setup script."""

from setuptools import find_packages, setup

with open('README.md') as readme_file:
    readme = readme_file.read()

install_requirements = [
    'coloredlogs==10.0',
    'Flask==1.0.2',
    'Flask-Cors==3.0.6',
    'flask-swagger==0.2.14',
    'flask-swagger-ui==3.20.9',
    'gunicorn==19.9.0',
    'PyYAML==5.1',
    'pytz==2018.5',
    'squid-py==0.5.14',
    'absl-py == 0.7.1',
    'astor == 0.7.1',
    'cachetools == 3.1.0',
    'chardet == 3.0.4',
    'gast == 0.2.2',
    'google-api-core == 1.9.0',
    'google-api-python-client == 1.7.8',
    'google-auth== 1.6.3',
    'google-auth-httplib2 == 0.0.3',
    'google-cloud-core == 0.29.1',
    'google-cloud-storage == 1.14.0',
    'google-cloud-vision == 0.36.0',
    'google-resumable-media == 0.3.2',
    'googleapis-common-protos == 1.5.9',
    'grpcio == 1.19.0',
    'httplib2 == 0.12.1',
    'idna == 2.8',
    #'keras-applications == 1.0.7',
    #'keras-preprocessing == 1.0.9',
    'markdown == 3.1',
    'mock == 2.0.0',
    'pbr == 5.1.3',
    'protobuf == 3.7.1',
    'pyasn1 == 0.4.5',
    'pyasn1-modules == 0.2.4',
    'requests == 2.21.0',
    'rsa == 4.0',
    #'tensorboard == 1.13.1',
    #'tensorflow == 1.13.1',
    #'tensorflow-estimator == 1.13.0',
    'termcolor == 1.1.0',
    'uritemplate == 3.0.0',
    'urllib3 == 1.24.1',
    'werkzeug == 0.15.2',
    'smbus-cffi == 0.5.1'
]

setup_requirements = ['pytest-runner==2.11.1', ]

dev_requirements = [
    'bumpversion==0.5.3',
    'pkginfo==1.4.2',
    'twine==1.11.0',
    # not virtualenv: devs should already have it before pip-installing
    'watchdog==0.8.3',
]

test_requirements = [
    'codacy-coverage==1.3.11',
    'coverage==4.5.1',
    'mccabe==0.6.1',
    'pylint==2.2.2',
    'pytest==3.4.2',
    'tox==3.2.1',
]

setup(
    author="leucothia",
    classifiers=[
        'Development Status :: 2 - Pre-Alpha',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: Apache Software License',
        'Natural Language :: English',
        'Programming Language :: Python :: 3.6',
        'Programming Language :: Python :: 3.7',
    ],
    description="🚗 Car backend.",
    extras_require={
        'test': test_requirements,
        'dev': dev_requirements + test_requirements,
    },
    include_package_data=True,
    install_requires=install_requirements,
    keywords='pines backend',
    license="Apache Software License 2.0",
    long_description=readme,
    long_description_content_type="text/markdown",
    name='car-backend',
    packages=find_packages(include=['flask_app', 'flask_app.myapp', 'camera']),
    setup_requires=setup_requirements,
    test_suite='tests',
    tests_require=test_requirements,
    url='https://github.com/odysseyhack/pines-and-electronics',
    version='0.1.0',
    zip_safe=False,
)
<file_sep># Take photos using RPI camera
#raspistill -t 10000 -tl 2000 -o ./images/
raspistill -t 10000 -tl 2000 -o /home/pi/git/pines-and-electronics/flask_app/images/image%04d.jpg

<file_sep>import pytest
from flask_app.flask_app.myapp import app

app = app

@pytest.fixture
def client():
    client = app.test_client()
    yield client<file_sep>from flask_app.camera.gcp_vision_multi_img import proccess_picture

# def test_status(client):
#     assert client.get('/api/status').data == b"status"
#     # client.get('/api/snap')
#
def test_register_in_ocean(client):
    client.get('/api/register')

# def test_process_pictures():
#     result = proccess_picture()<file_sep># Import basic packages
import io
import logging
import os
import glob
import warnings

warnings.filterwarnings('ignore')

from time import gmtime, strftime


# Imports the Google Cloud client library
from google.cloud import vision
from google.cloud.vision import types

# Instantiates a client
client = vision.ImageAnnotatorClient()

# Path storing Pi camera photos
img_path = './images'


# Classification using Google Vision API
def proccess_picture():
    for img in os.listdir(img_path):
        if img.endswith('.jpg'):
            image = os.path.join(img_path, img)
            logging.info(image)

            with io.open(image, 'rb') as image_file:
                content = image_file.read()

                image = types.Image(content=content)

                response = client.label_detection(image=image)
                labels = response.label_annotations
                logging.info(strftime('%Y-%m-%d %H:%M:%S', gmtime()))
                logging.info('Labels:')
                result = []
                for label in labels:
                    logging.info(label)
                    result.append(label.description)
                return result
<file_sep>from backend.car.car_controller import CarController


def test_car_controller():
    car = CarController()
    send_command = car.send_command('status')
    assert send_command
    filter = car.contract.events.CarCommandSent.createFilter(fromBlock=0, toBlock='latest')
    logs = filter.get_all_entries()
    assert len(logs) > 0
    event = car.subscribe_to_command_event(
        20,
        car.log_event(car.COMMAND_SENT_EVENT),
        (),
        wait=True
    )
    assert event, 'no event for command_sent_event'
    assert car.parse_command(logs[-1]) == "status"
<file_sep>from backend.car.car_controller import CarController

class main():
    car = CarController()
    last_block_number = 0
    while True:
        filter = car.contract.events.CarCommandSent.createFilter(fromBlock=0, toBlock='latest')
        logs = filter.get_all_entries()
        block_number = logs[-1].blockNumber
        if block_number != last_block_number:
            car.execute_command(car.parse_command(logs[-1]))
            last_block_number= block_number


if __name__ == '__main__':
    main()<file_sep>import json
import logging
import requests

from car.event_listener import EventListener
from squid_py.config import Config
from squid_py.config_provider import ConfigProvider
from squid_py.keeper.web3_provider import Web3Provider
from web3.contract import ConciseContract


class CarController:
    CONTRACT_NAME = 'CarController'

    def __init__(self):
        self.config = Config('config.ini')
        self.COMMAND_SENT_EVENT = 'CarCommandSent'
        ConfigProvider.set_config(self.config)

    @property
    def contract(self):
        return Web3Provider.get_web3().eth.contract(
            address=self.config.get('resources', 'car.contract.address'),
            abi=self.get_abi('artifacts/CarController.json')['abi']
        )

    @property
    def contract_concise(self):
        return ConciseContract(Web3Provider.get_web3().eth.contract(
            address=self.config.get('resources', 'car.contract.address'),
            abi=self.get_abi('artifacts/CarController.json')['abi']
        ))

    @staticmethod
    def get_abi(path):
        with open(path) as f:
            contract_dict = json.loads(f.read())
            return contract_dict

    def send_command(self, command):
        """

        :param command:
        :return:
        """
        logging.info(f'Sending commnad {command} to the car.')
        return self.contract.functions.sendCommand(command).transact()

    def subscribe_to_event(self, event_name, timeout, event_filter, callback=False,
                           timeout_callback=None, args=None, wait=False):
        return EventListener(
            self.contract,
            event_name,
            args,
            filters=event_filter
        ).listen_once(
            callback,
            timeout_callback=timeout_callback,
            timeout=timeout,
            blocking=wait
        )

    def subscribe_to_command_event(self, timeout, callback, args, wait=False):
        return self.subscribe_to_event(
            self.COMMAND_SENT_EVENT,
            timeout,
            # {'_command': 'Forward'},
            None,
            callback=callback,
            args=args,
            wait=wait
        )

    @staticmethod
    def log_event(event_name):
        def _process_event(event):
            print(f'Received event {event_name}: {event}')
        return _process_event

    def parse_command(self, event):
        if event is None:
            logging.error('No event to parse.')
        if event.args is None:
            logging.info('There are no commnads in this event')
        command = event.args._command
        return command

    def execute_command(self, command):
        logging.info(f'Calling command:{command}')
        if command.startswith('status'):
            requests.get(f'{self.config.get("resources","raspberry.url")}/api/status')
        elif command.startswith('snap'):
            requests.get(f'{self.config.get("resources", "raspberry.url")}/api/snap')
        elif command.startswith('register'):
            requests.post(f'{self.config.get("resources", "raspberry.url")}/api/register')
        elif command.startswith('snapshot'):
            requests.get(f'{self.config.get("resources", "raspberry.url")}/api/snapshot')
        elif command.startswith('linear'):
            requests.get(f'{self.config.get("resources", "raspberry.url")}/api/linear')
        elif command.startswith('steer'):
            requests.get(f'{self.config.get("resources", "raspberry.url")}/api/steer')
        else:
            logging.error(f'Invalid command: {command}')

    # def do_request(self):
    #     try:
    #         requests.get(f'{self.config.get("resources", "raspberry.url")}/api/snapshot')
    #     except:
<file_sep>> ![banner](https://www.odyssey.org/wp-content/uploads/2018/12/Nature2.0-logo-e1545922454827.png)
<h1 align="center">Pines & Electronics</h1>


> 🕹🚗 Hacking in the Nature2.0 track.


---
## Table of Contents

  - [📄 DAO](#dao)
  - [🔙🔚 Backend](#backend)
  - [🌿 API](#api)
  - [🏛 License](#license)

---

## 📄 DAO
This component has a simple smart contract that emit an event with the command that we want to 
send to the robotic car.
First of all we need to compile the contract and generate the abi files:
```bash
npx install
npx truffle compile
```
To deploy the contract we need to run the following commands:
```bash
npx truffle deploy
```
Once this happen we can get the abi files from the build folder to interact with the contracts 
and the address of the contract.

## 🔙🔚 Backend

## 🌿 API

## 🏛 License

```text
Copyright 2018 

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```<file_sep>

# Activate conda environment
source activate pines_conda

# Connect to google API and predict
python ./image_demo/gcp_vision_multi_img.py
