completed SMS gateway project
This commit is contained in:
4
app/channels/application_cable/channel.rb
Normal file
4
app/channels/application_cable/channel.rb
Normal file
@@ -0,0 +1,4 @@
|
||||
module ApplicationCable
|
||||
class Channel < ActionCable::Channel::Base
|
||||
end
|
||||
end
|
||||
31
app/channels/application_cable/connection.rb
Normal file
31
app/channels/application_cable/connection.rb
Normal file
@@ -0,0 +1,31 @@
|
||||
module ApplicationCable
|
||||
class Connection < ActionCable::Connection::Base
|
||||
identified_by :current_gateway
|
||||
|
||||
def connect
|
||||
self.current_gateway = find_verified_gateway
|
||||
logger.info "Gateway #{current_gateway.device_id} connected"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_verified_gateway
|
||||
# Get API key from request params
|
||||
api_key = request.params[:api_key]
|
||||
|
||||
if api_key.blank?
|
||||
reject_unauthorized_connection
|
||||
end
|
||||
|
||||
# Hash the API key and find gateway
|
||||
api_key_digest = Digest::SHA256.hexdigest(api_key)
|
||||
gateway = Gateway.find_by(api_key_digest: api_key_digest, active: true)
|
||||
|
||||
if gateway
|
||||
gateway
|
||||
else
|
||||
reject_unauthorized_connection
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
99
app/channels/gateway_channel.rb
Normal file
99
app/channels/gateway_channel.rb
Normal file
@@ -0,0 +1,99 @@
|
||||
class GatewayChannel < ApplicationCable::Channel
|
||||
def subscribed
|
||||
# Gateway is already authenticated at the connection level
|
||||
# current_gateway is set by ApplicationCable::Connection
|
||||
@gateway = current_gateway
|
||||
|
||||
unless @gateway
|
||||
reject
|
||||
return
|
||||
end
|
||||
|
||||
# Subscribe to gateway-specific channel
|
||||
stream_for @gateway
|
||||
|
||||
# Update gateway status
|
||||
@gateway.heartbeat!
|
||||
|
||||
Rails.logger.info("Gateway #{@gateway.device_id} subscribed to GatewayChannel")
|
||||
end
|
||||
|
||||
def unsubscribed
|
||||
# Update gateway status when disconnected
|
||||
if @gateway
|
||||
@gateway.mark_offline!
|
||||
Rails.logger.info("Gateway #{@gateway.device_id} disconnected from WebSocket")
|
||||
end
|
||||
end
|
||||
|
||||
def receive(data)
|
||||
return unless @gateway
|
||||
|
||||
# Handle incoming messages from gateway
|
||||
case data["action"]
|
||||
when "heartbeat"
|
||||
handle_heartbeat(data)
|
||||
when "delivery_report"
|
||||
handle_delivery_report(data)
|
||||
when "message_received"
|
||||
handle_message_received(data)
|
||||
else
|
||||
Rails.logger.warn("Unknown action received: #{data['action']}")
|
||||
end
|
||||
rescue StandardError => e
|
||||
Rails.logger.error("Error processing gateway message: #{e.message}")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def handle_heartbeat(data)
|
||||
@gateway.heartbeat!
|
||||
|
||||
# Update metadata if provided
|
||||
metadata = {
|
||||
battery_level: data["battery_level"],
|
||||
signal_strength: data["signal_strength"],
|
||||
messages_in_queue: data["messages_in_queue"]
|
||||
}.compact
|
||||
|
||||
@gateway.update(metadata: metadata) if metadata.any?
|
||||
end
|
||||
|
||||
def handle_delivery_report(data)
|
||||
message_id = data["message_id"]
|
||||
status = data["status"]
|
||||
error_message = data["error_message"]
|
||||
|
||||
sms = SmsMessage.find_by(message_id: message_id)
|
||||
return unless sms
|
||||
|
||||
case status
|
||||
when "delivered"
|
||||
sms.mark_delivered!
|
||||
when "failed"
|
||||
sms.mark_failed!(error_message)
|
||||
RetryFailedSmsJob.perform_later(sms.id) if sms.can_retry?
|
||||
end
|
||||
end
|
||||
|
||||
def handle_message_received(data)
|
||||
sender = data["sender"]
|
||||
message = data["message"]
|
||||
timestamp = data["timestamp"] || Time.current
|
||||
|
||||
# Create inbound SMS
|
||||
sms = SmsMessage.create!(
|
||||
gateway: @gateway,
|
||||
direction: "inbound",
|
||||
phone_number: sender,
|
||||
message_body: message,
|
||||
status: "delivered",
|
||||
delivered_at: timestamp
|
||||
)
|
||||
|
||||
@gateway.increment_received_count!
|
||||
|
||||
# Process inbound message
|
||||
ProcessInboundSmsJob.perform_later(sms.id)
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user