Implementar API híbrida

This commit is contained in:
f 2021-12-06 20:00:04 -03:00
parent 6e5336f9bb
commit 4c1eac1f2b
14 changed files with 191 additions and 43 deletions

View file

@ -1,10 +1,59 @@
# frozen_string_literal: true
class ApiController < ActionController::API
# Por ahora hacer un echo de cada transacción
#
# TODO: Habilitar esto de alguna forma.
skip_forgery_protection
rescue_from ActiveRecord::RecordNotFound, with: :bad_request_error
rescue_from ActionController::ParameterMissing, with: :bad_request_error
# @see {https://docutopia.tupale.co/sutty:nodemecu:api}
def transactions
render plain: params[:transaction_uuid], status: :ok
Transaction.transaction do
transaction = raspberry.transactions.build transaction_params
transaction.id = params[:transaction_uuid]
# TODO: Verificar firma
transaction.signature = headers[:'X-Signature']
params[:arduinos]&.each do |a|
arduino = transaction.arduinos.build local_id: a[:id]
a[:sensores]&.each do |s|
arduino.sensors.build(sensor_params s)
end
end
if transaction.save
render plain: transaction.uuid, status: :ok
else
head :bad_request
end
end
end
private
def bad_request_error
head :bad_request
end
def raspberry
@raspberry ||= Raspberry.find params[:controller_id]
end
# Procesa la transacción
def transaction_params
@transaction_params ||= params.permit(:controller_id,
:timestamp,
:error_code,
:battery_status,
:sample,
:signature,
coordinates: %i[lat lng])
end
# Procesa los parámetros de un sensor
def sensor_params(sensor)
sensor.permit(:timestamp, :type, :value, :unit, :error)
end
end

View file

@ -1,10 +0,0 @@
# frozen_string_literal: true
class MeasurementsController < ApplicationController
protect_from_forgery with: :null_session
def create
sensor = Sensor.find_or_create_by id: params[:sensor_id]
sensor.measurements.create params.permit(:temperature, :level, :flow, :turbidity, :conductivity, :ph)
end
end

7
app/models/arduino.rb Normal file
View file

@ -0,0 +1,7 @@
# frozen_string_literal: true
class Transaction < ApplicationRecord
belongs_to :raspberry
belongs_to :transaction
has_many :sensores
end

6
app/models/raspberry.rb Normal file
View file

@ -0,0 +1,6 @@
# frozen_string_literal: true
class Raspberry < ApplicationRecord
has_many :transactions
has_many :arduinos
end

View file

@ -1,5 +1,5 @@
# frozen_string_literal: true
class Sensor < ApplicationRecord
has_many :measurements
belongs_to :arduino
end

View file

@ -0,0 +1,6 @@
# frozen_string_literal: true
class Transaction < ApplicationRecord
belongs_to :raspberry
has_many :arduinos
end

View file

@ -1,16 +1,5 @@
# Be sure to restart your server when you modify this file.
# frozen_string_literal: true
# Add new inflection rules using the following format. Inflections
# are locale specific, and you may define rules for as many different
# locales as you wish. All of these examples are active by default:
# ActiveSupport::Inflector.inflections(:en) do |inflect|
# inflect.plural /^(ox)$/i, '\1en'
# inflect.singular /^(ox)en/i, '\1'
# inflect.irregular 'person', 'people'
# inflect.uncountable %w( fish sheep )
# end
# These inflection rules are supported but not enabled by default:
# ActiveSupport::Inflector.inflections(:en) do |inflect|
# inflect.acronym 'RESTful'
# end
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.irregular 'raspberry', 'raspberries'
end

View file

@ -1,7 +1,7 @@
# frozen_string_literal: true
class CreateSensor < ActiveRecord::Migration[6.1]
def change
create_table :sensors do |t|
t.string :nombre, unique: true, index: true
t.timestamps
end

View file

@ -0,0 +1,20 @@
# frozen_string_literal: true
# Crea las transacciones
class CreateTransactions < ActiveRecord::Migration[6.1]
def change
enable_extension :pgcrypto
create_table :transactions, id: :uuid do |t|
t.timestamps
t.uuid :raspberry_id, index: true
t.datetime :timestamp
t.string :error_code
t.jsonb :coordinates
t.string :battery_status
t.string :sample
t.string :storage
t.string :signature
end
end
end

View file

@ -0,0 +1,13 @@
# frozen_string_literal: true
class CreateRaspberries < ActiveRecord::Migration[6.1]
def change
enable_extension :pgcrypto
create_table :raspberries, id: :uuid do |t|
t.timestamps
t.string :name
t.string :public_key
end
end
end

View file

@ -0,0 +1,12 @@
# frozen_string_literal: true
class CreateArduinos < ActiveRecord::Migration[6.1]
def change
create_table :arduinos, id: :uuid do |t|
t.timestamps
t.uuid :raspberry_id, index: true
t.uuid :transaction_id, index: true
t.integer :local_id
end
end
end

View file

@ -0,0 +1,7 @@
# frozen_string_literal: true
class DropMeasurements < ActiveRecord::Migration[6.1]
def change
drop_table :measurements
end
end

View file

@ -0,0 +1,25 @@
# frozen_string_literal: true
class ChangeSensors < ActiveRecord::Migration[6.1]
def up
drop_table :sensors
create_table :sensors, id: :uuid do |t|
t.timestamps
t.uuid :arduino_id, index: true
t.datetime :timestamp
t.string :type, index: true
t.integer :value
t.string :unit
end
end
def down
drop_table :sensors
create_table :sensors do |t|
t.string :nombre, unique: true, index: true
t.timestamps
end
end
end

50
db/schema.rb generated
View file

@ -10,11 +10,22 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2021_07_26_182544) do
ActiveRecord::Schema.define(version: 2021_12_06_224353) do
# These are extensions that must be enabled in order to support this database
enable_extension "pgcrypto"
enable_extension "plpgsql"
create_table "arduinos", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.uuid "raspberry_id"
t.uuid "transaction_id"
t.integer "local_id"
t.index ["raspberry_id"], name: "index_arduinos_on_raspberry_id"
t.index ["transaction_id"], name: "index_arduinos_on_transaction_id"
end
create_table "blazer_audits", force: :cascade do |t|
t.bigint "user_id"
t.bigint "query_id"
@ -71,24 +82,37 @@ ActiveRecord::Schema.define(version: 2021_07_26_182544) do
t.index ["creator_id"], name: "index_blazer_queries_on_creator_id"
end
create_table "measurements", force: :cascade do |t|
t.decimal "temperature"
t.decimal "level"
t.decimal "ph"
t.decimal "turbidity"
t.decimal "conductivity"
t.decimal "flow"
t.bigint "sensor_id"
create_table "raspberries", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["sensor_id"], name: "index_measurements_on_sensor_id"
t.string "name"
t.string "public_key"
end
create_table "sensors", force: :cascade do |t|
t.string "nombre"
create_table "sensors", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["nombre"], name: "index_sensors_on_nombre"
t.uuid "arduino_id"
t.datetime "timestamp"
t.string "type"
t.integer "value"
t.string "unit"
t.index ["arduino_id"], name: "index_sensors_on_arduino_id"
t.index ["type"], name: "index_sensors_on_type"
end
create_table "transactions", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.uuid "raspberry_id"
t.datetime "timestamp"
t.string "error_code"
t.jsonb "coordinates"
t.string "battery_status"
t.string "sample"
t.string "storage"
t.string "signature"
t.index ["raspberry_id"], name: "index_transactions_on_raspberry_id"
end
create_table "users", force: :cascade do |t|