Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ services:
PG_DATABASE_URL: ${PG_DATABASE_URL:-postgresql://postgres:password@postgres:5432/model_dev}

postgres:
image: postgres:17-alpine
image: postgres:18-alpine
healthcheck:
test: [ "CMD-SHELL", "pg_isready -U postgres" ]
interval: 30s
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
-- +micrate Up
-- SQL in section 'Up' is executed when this migration is applied

ALTER TABLE "sys" ADD COLUMN IF NOT EXISTS camera_snapshot_urls TEXT[] DEFAULT '{}';
UPDATE "sys" SET camera_snapshot_urls[1] = camera_snapshot_url WHERE camera_snapshot_url IS NOT NULL;

ALTER TABLE "driver" ADD COLUMN IF NOT EXISTS alert_level public.alert_severity NOT NULL DEFAULT 'MEDIUM'::public.alert_severity;
ALTER TABLE "mod" ADD COLUMN IF NOT EXISTS alert_level public.alert_severity NOT NULL DEFAULT 'MEDIUM'::public.alert_severity;

-- +micrate Down
-- SQL section 'Down' is executed when this migration is rolled back

ALTER TABLE "driver" DROP COLUMN IF EXISTS alert_level;
ALTER TABLE "mod" DROP COLUMN IF EXISTS alert_level;
ALTER TABLE "sys" DROP COLUMN IF EXISTS camera_snapshot_urls;
20 changes: 20 additions & 0 deletions spec/control_system_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,26 @@ module PlaceOS::Model
end
end

describe "camera_snapshot_urls" do
it "setting camera_snapshot_url updates camera_snapshot_urls" do
control_system = Generator.control_system
control_system.camera_snapshot_url = "https://placeos.com/"
control_system.save!
control_system.reload!
control_system.camera_snapshot_urls[0]?.should eq control_system.camera_snapshot_url
control_system.destroy
end

it "setting camera_snapshot_urls updates camera_snapshot_url" do
control_system = Generator.control_system
control_system.camera_snapshot_urls = ["https://placeos.com/"]
control_system.save!
control_system.reload!
control_system.camera_snapshot_url.should eq control_system.camera_snapshot_urls[0]
control_system.destroy
end
end

describe "remove_module" do
it "removes a module if present" do
control_system = Generator.control_system
Expand Down
42 changes: 41 additions & 1 deletion src/placeos-models/control_system.cr
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@
attribute support_url : String = ""
attribute timetable_url : String? # The timetable visualisation
attribute camera_snapshot_url : String? # snapshot images of the room
attribute camera_url : String? # admin control
attribute camera_snapshot_urls : Array(String) = -> { [] of String }
attribute camera_url : String? # admin control

# if not bookable via google / O365 calendaring systems
attribute room_booking_url : String?
Expand Down Expand Up @@ -110,10 +111,49 @@

# Validate support URI
validate ->(this : ControlSystem) {
if url = this.camera_snapshot_url
this.validation_error(:camera_snapshot_url, "is an invalid URI") unless Validation.valid_uri?(url)
end

this.camera_snapshot_urls.each do |url|

Check warning on line 118 in src/placeos-models/control_system.cr

View workflow job for this annotation

GitHub Actions / Ameba

Lint/ShadowingOuterLocalVar

Shadowing outer local variable `url`
Raw output
> this.camera_snapshot_urls.each do |url|
                                     ^
if !Validation.valid_uri?(url)
this.validation_error(:camera_snapshot_urls, "contains an invalid URI")
break
end
end

return if this.support_url.blank?
this.validation_error(:support_url, "is an invalid URI") unless Validation.valid_uri?(this.support_url)
}

before_save :unique_camera_urls

def unique_camera_urls
update_camera_urls
unique_urls = self.camera_snapshot_urls.uniq
if unique_urls.size != self.camera_snapshot_urls.size
self.camera_snapshot_urls = unique_urls
end
end

def update_camera_urls
url = camera_snapshot_url
if camera_snapshot_urls.size == 1 && url && !@camera_snapshot_urls_changed && @camera_snapshot_url_changed
self.camera_snapshot_urls[0] = url
@camera_snapshot_urls_changed = true
elsif url && camera_snapshot_urls.empty?
camera_snapshot_urls.insert(0, url)
@camera_snapshot_urls_changed = true
end
self.camera_snapshot_url = camera_snapshot_urls.first?
end

def camera_snapshot_urls=(vals : Array(String))
@camera_snapshot_urls = vals
@camera_snapshot_urls_changed = true
vals
end

# Queries
###############################################################################################

Expand Down
3 changes: 3 additions & 0 deletions src/placeos-models/driver.cr
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ module PlaceOS::Model

attribute role : Role, es_type: "integer", converter: Enum::ValueConverter(PlaceOS::Model::Driver::Role)

attribute alert_level : Alert::Severity = Alert::Severity::MEDIUM, converter: PlaceOS::Model::PGEnumConverter(PlaceOS::Model::Alert::Severity),
description: "the default alert level for stagehand issues"

# Path to driver, relative to repository directory
attribute file_name : String

Expand Down
9 changes: 9 additions & 0 deletions src/placeos-models/module.cr
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ module PlaceOS::Model
# Cache the module's driver role locally for load order
attribute role : Driver::Role, es_type: "integer", converter: Enum::ValueConverter(PlaceOS::Model::Driver::Role)

attribute alert_level : Alert::Severity?, converter: PlaceOS::Model::PGEnumConverter(PlaceOS::Model::Alert::Severity),
description: "the alert level for stagehand issues"

# Connected state in model so we can filter and search on it
attribute connected : Bool = true
attribute running : Bool = false
Expand Down Expand Up @@ -228,6 +231,8 @@ module PlaceOS::Model
# NOTE: Temporary while `edge` feature developed
before_create :set_edge_hint

before_create :set_alert_level

# Logic modules are automatically added to the ControlSystem
#
protected def add_logic_module
Expand Down Expand Up @@ -275,6 +280,10 @@ module PlaceOS::Model
end
end

protected def set_alert_level
self.alert_level = driver.try(&.alert_level) || Alert::Severity::MEDIUM if self.alert_level.nil?
end

# Overridden attribute accessors
###############################################################################################

Expand Down
2 changes: 1 addition & 1 deletion src/placeos-models/utilities/id_generator.cr
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class PlaceOS::Model::Utilities::IdGenerator

# Provides a channel with an infinite stream of psuedo-random values up to
# *max* size and a guaranteed cycle of at least *max* samples.
private def self.seq(max = UInt32::MAX, r = Random::DEFAULT)
private def self.seq(max = UInt32::MAX, r = Random.new)
ch = Channel(UInt32).new
spawn do
loop do
Expand Down