Created
May 25, 2010 23:08
-
-
Save lightcap/413806 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require 'rexml/document' | |
| require "models/prog_const.rb" | |
| # TODO: MK Get rid of all vestiges of Dupin's global cache that doesn't cache anything. | |
| $prog_const = ProgConst.new if $prog_const.nil? | |
| $prog_const.check_reload | |
| #This object holds all the required information about a PVM post the system | |
| #will need to work with the xml message | |
| # | |
| class PostPackage | |
| attr_accessor :serial_number, :text_serial, :message_type, :poll_count, :poll_interval, | |
| :xml, :mac_address, :ip_address, :timestamp_on | |
| #Population code, this code is made to be very quick | |
| def populate( ip_address, mac_address, xml, timestamp_on ) | |
| #Store the basic data we are just given here | |
| @ip_address = ip_address.gsub(/[^\.0-9]/, '') | |
| @mac_address = mac_address.upcase.gsub(/[^A-F0-9]/, '') | |
| @xml = xml | |
| @timestamp_on = timestamp_on | |
| #Figure out what the serial number of this thing is | |
| regex = /<inverter_serial>([^>]*)<\/inverter_serial>/.match(xml) || /<serial_number>([^>]*)<\/serial_number>/.match(xml) | |
| @serial_number = regex[1] unless regex.nil? | |
| regex = /<text_serial>([^>]*)<\/text_serial>/.match(xml) | |
| @text_serial = regex[1] unless regex.nil? | |
| @firmware_version = determine_firmware | |
| #Figure out what the message type and the poll count | |
| if (regex = /(<message[^>]*>)/.match(xml)) | |
| mesg = regex[1] | |
| #Get the poll count | |
| @poll_count = regex[1].to_i if (regex = | |
| /poll_count=['"]([0-9]+)['"]/.match(mesg)) | |
| #Get the poll interval in seconds | |
| @poll_interval = regex[1].to_i if (regex = | |
| /poll_interval=['"]([0-9]+)['"]/.match(mesg)) | |
| #Get the poll count | |
| @message_type = regex[1] if (regex = | |
| /type=['"]([a-zA-Z0-9]+)['"]/.match(mesg)) | |
| end | |
| #check if we are valid or not | |
| if @serial_number.nil? or @poll_count.nil? or @poll_interval.nil? or @message_type.nil? or @mac_address.nil? | |
| @valid = false | |
| else | |
| @valid = true | |
| end | |
| self | |
| end | |
| def data | |
| @data ||= load_from_xml(extract_message(self.xml)) | |
| end | |
| def validate(package_validator = nil) | |
| if package_validator.nil? | |
| @post_val = PostValidator.new(self) | |
| @post_val.validate | |
| end | |
| end | |
| def errors | |
| @post_val.errors unless @post_val.nil? | |
| end | |
| def safe_inv_model | |
| return @post_val.inv_model || $prog_const.inv_models.first | |
| end | |
| def inv_model | |
| @post_val.inv_model | |
| end | |
| #Return true, false/nil if we are valid | |
| def valid? | |
| validate if @post_val.nil? | |
| return @valid && @post_val.valid? | |
| end | |
| def serial_number_valid? | |
| validate if @post_val.nil? | |
| @post_val.serial_number_valid? | |
| end | |
| def text_serial_valid? | |
| validate if @post_val.nil? | |
| @post_val.text_serial_valid? | |
| end | |
| def segis? | |
| # Right now, versions aren't allowed to be released with point version numbers. So straight float comparisions will work, here. | |
| ((@firmware_version >= Gem::Version.create("2.18") && @firmware_version < Gem::Version.create("3.0") && scaling?) || | |
| @firmware_version >= Gem::Version.create("3.2") || string_combiner? || weather_station?) | |
| end | |
| def scaling? | |
| match = /<scaling>([^>]*)<\/scaling>/.match(xml) | |
| return @scaling = /<scaling>([^>]*)<\/scaling>/.match(xml)[1].to_f === 1 unless match.nil? | |
| return false | |
| end | |
| # Returns true if xml contains both <string_combiner> and </string_combiner> tags | |
| def string_combiner? | |
| ! /<string_combiner [^>]*>/.match(xml).nil? and ! /<\/string_combiner>/.match(xml).nil? | |
| end | |
| # Returns true if xml contains both <weather_station> and </weather_station> tags | |
| def weather_station? | |
| ! /<weather_station [^>]*>/.match(xml).nil? and ! /<\/weather_station>/.match(xml).nil? | |
| end | |
| def extra_stuff? | |
| string_combiner? || weather_station? | |
| end | |
| #dump this info | |
| def debug | |
| return "PackageDump, Mac Address #{@mac_address}, IP Addresss #{@ip_address}, Serial #{@serial_number}, Type #{@message_type}, Count #{@poll_count}" | |
| end | |
| private | |
| def determine_firmware | |
| ver = /<firmware_version>([^>]*)<\/firmware_version>/.match(@xml) || /<version_firmware>([^>]*)<\/version_firmware>/.match(@xml) | |
| @firmware_version = Gem::Version.create(ver[1]) | |
| end | |
| def extract_message(raw_xml) | |
| unless raw_xml | |
| @log.error{"Starlink #{@sl.mac_address} posted no data, no use going on..."} | |
| return nil | |
| else | |
| doc = REXML::Document.new(raw_xml) | |
| xml = doc.root | |
| end | |
| end | |
| def load_from_xml(xml) | |
| dx = DatacomXML.load_from_xml(xml) | |
| end | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require "models/prog_const.rb" | |
| $prog_const = ProgConst.new if $prog_const.nil? | |
| $prog_const.check_reload | |
| class PostValidator | |
| attr_accessor :errors | |
| #Information that was store while these checks were conducted | |
| attr_reader :inv_model | |
| # When this object is created, nothing is valid, what a negative guy! | |
| def initialize(package) | |
| @package = package | |
| @serial_valid = false | |
| @msg_valid = false | |
| @errors = Array.new | |
| @validated = false | |
| @inv_model = nil | |
| end | |
| # Check if the serial number is valid | |
| def validate_serials | |
| ret_status = true | |
| @serial_number_valid = true | |
| @text_serial_valid = true | |
| if !((13..14) === @package.serial_number.length) | |
| errors.push( 'Invalid serial number length' ) | |
| @serial_number_valid = false | |
| end | |
| if @package.serial_number[-8..-1] =~ /[0]{8,}$/ | |
| errors.push('Invalid serial number last 8 chars all zeros') | |
| @serial_number_valid = false | |
| end | |
| if @package.text_serial.nil? | |
| errors.push( 'Invalid text serial does not exist') | |
| @text_serial_valid = false | |
| end | |
| unless @package.text_serial.nil? | |
| unless @package.text_serial.length >= 10 | |
| errors.push( 'Invalid text serial length' ) | |
| @text_serial_valid = false | |
| end | |
| if @package.text_serial[-10..-1] =~ /[0]{10,}$/ | |
| errors.push( 'Invalid text serial last 10 chars all zeros') | |
| @text_serial_valid = false | |
| end | |
| end | |
| unless @package.serial_number.nil? | |
| model = @package.serial_number[0..3].to_i | |
| @inv_model = $prog_const.inv_model_hash[model] | |
| end | |
| #Check that this model exists | |
| if @inv_model.nil? | |
| errors.push( "Invalid inverter model number" ) | |
| @serial_number_valid = false | |
| end | |
| @serial_valid = (text_serial_valid? || serial_number_valid?) | |
| return @serial_valid | |
| end | |
| # Check that the message type is valid | |
| def validate_msg_type | |
| return @msg_valid = true if $prog_const.msg_type_hash.has_key?(@package.message_type.to_sym) | |
| #This thing didn't work, so quit out | |
| @errors.push( "Invalid message type (#{@package.message_type})" ) | |
| return false | |
| end | |
| def validate | |
| @serial_valid = validate_serials | |
| @msg_valid = validate_msg_type | |
| @validated = true | |
| end | |
| # Return the validity of the object | |
| def valid? | |
| validate unless @validated | |
| return (@serial_valid and @msg_valid) | |
| end | |
| def serial_number_valid? | |
| @serial_number_valid | |
| end | |
| def text_serial_valid? | |
| @text_serial_valid | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment