diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..d203057
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,766 @@
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 4
+indent_style = space
+insert_final_newline = true
+max_line_length = 200
+tab_width = 4
+ij_continuation_indent_size = 8
+ij_formatter_off_tag = @formatter:off
+ij_formatter_on_tag = @formatter:on
+ij_formatter_tags_enabled = false
+ij_smart_tabs = false
+ij_wrap_on_typing = false
+
+[*.css]
+ij_css_align_closing_brace_with_properties = false
+ij_css_blank_lines_around_nested_selector = 1
+ij_css_blank_lines_between_blocks = 1
+ij_css_brace_placement = 0
+ij_css_hex_color_long_format = false
+ij_css_hex_color_lower_case = false
+ij_css_hex_color_short_format = false
+ij_css_hex_color_upper_case = false
+ij_css_keep_blank_lines_in_code = 2
+ij_css_keep_indents_on_empty_lines = false
+ij_css_keep_single_line_blocks = false
+ij_css_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
+ij_css_space_after_colon = true
+ij_css_space_before_opening_brace = true
+ij_css_value_alignment = 0
+
+[*.csv]
+max_line_length = 2147483647
+ij_csv_wrap_long_lines = false
+
+[*.less]
+indent_size = 2
+ij_less_align_closing_brace_with_properties = false
+ij_less_blank_lines_around_nested_selector = 1
+ij_less_blank_lines_between_blocks = 1
+ij_less_brace_placement = 0
+ij_less_hex_color_long_format = false
+ij_less_hex_color_lower_case = false
+ij_less_hex_color_short_format = false
+ij_less_hex_color_upper_case = false
+ij_less_keep_blank_lines_in_code = 2
+ij_less_keep_indents_on_empty_lines = false
+ij_less_keep_single_line_blocks = false
+ij_less_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
+ij_less_space_after_colon = true
+ij_less_space_before_opening_brace = true
+ij_less_value_alignment = 0
+
+[*.pm]
+ij_continuation_indent_size = 4
+ij_perl5_align_attributes = false
+ij_perl5_align_comments_on_consequent_lines = true
+ij_perl5_align_consecutive_assignments = 0
+ij_perl5_align_fat_comma = true
+ij_perl5_align_multiline_array_initializer_expression = false
+ij_perl5_align_multiline_binary_operation = false
+ij_perl5_align_multiline_chained_methods = false
+ij_perl5_align_multiline_parameters = true
+ij_perl5_align_multiline_parameters_in_calls = false
+ij_perl5_align_multiline_ternary_operation = false
+ij_perl5_align_qw_elements = false
+ij_perl5_align_variable_declarations = false
+ij_perl5_array_initializer_wrap = off
+ij_perl5_assignment_wrap = off
+ij_perl5_attributes_wrap = 0
+ij_perl5_binary_operation_sign_on_next_line = false
+ij_perl5_binary_operation_wrap = off
+ij_perl5_brace_style_compound = 0
+ij_perl5_brace_style_namespace = 0
+ij_perl5_brace_style_sub = 0
+ij_perl5_call_parameters_wrap = off
+ij_perl5_else_on_new_line = true
+ij_perl5_keep_indents_on_empty_lines = false
+ij_perl5_main_format = 0
+ij_perl5_method_call_chain_wrap = off
+ij_perl5_method_parameters_wrap = off
+ij_perl5_optional_dereference = 0
+ij_perl5_optional_dereference_hashref_element = 0
+ij_perl5_optional_dereference_simple = 0
+ij_perl5_optional_parentheses = 0
+ij_perl5_optional_quotes = 0
+ij_perl5_optional_quotes_hash_index = 0
+ij_perl5_optional_quotes_heredoc_opener = 0
+ij_perl5_place_assignment_sign_on_next_line = false
+ij_perl5_qw_list_wrap = 0
+ij_perl5_space_after_colon = true
+ij_perl5_space_after_comma = true
+ij_perl5_space_after_for_semicolon = true
+ij_perl5_space_after_quest = true
+ij_perl5_space_after_variable_declaration_keyword = true
+ij_perl5_space_before_attribute = true
+ij_perl5_space_before_colon = true
+ij_perl5_space_before_comma = false
+ij_perl5_space_before_do_left_brace = true
+ij_perl5_space_before_else_keyword = true
+ij_perl5_space_before_for_semicolon = false
+ij_perl5_space_before_if_left_brace = true
+ij_perl5_space_before_if_parentheses = true
+ij_perl5_space_before_method_parentheses = false
+ij_perl5_space_before_quest = true
+ij_perl5_space_within_empty_method_parentheses = false
+ij_perl5_spaces_around_additive_operators = true
+ij_perl5_spaces_around_assignment_operators = true
+ij_perl5_spaces_around_bitwise_operators = true
+ij_perl5_spaces_around_concat_operator = true
+ij_perl5_spaces_around_equality_operators = true
+ij_perl5_spaces_around_logical_operators = true
+ij_perl5_spaces_around_multiplicative_operators = true
+ij_perl5_spaces_around_range_operators = true
+ij_perl5_spaces_around_relational_operators = true
+ij_perl5_spaces_around_shift_operators = true
+ij_perl5_spaces_around_unary_operator = false
+ij_perl5_spaces_within_anon_array = true
+ij_perl5_spaces_within_anon_hash = true
+ij_perl5_spaces_within_braces = false
+ij_perl5_spaces_within_if_parentheses = false
+ij_perl5_spaces_within_method_call_parentheses = false
+ij_perl5_spaces_within_method_parentheses = false
+ij_perl5_spaces_within_parentheses = false
+ij_perl5_spaces_within_qw_quotes = false
+ij_perl5_ternary_operation_signs_on_next_line = false
+ij_perl5_ternary_operation_wrap = off
+ij_perl5_variable_declaration_wrap = 0
+ij_perl5_wrap_comments = false
+
+[*.properties]
+ij_properties_align_group_field_declarations = false
+
+[*.sass]
+indent_size = 2
+ij_sass_align_closing_brace_with_properties = false
+ij_sass_blank_lines_around_nested_selector = 1
+ij_sass_blank_lines_between_blocks = 1
+ij_sass_brace_placement = 0
+ij_sass_hex_color_long_format = false
+ij_sass_hex_color_lower_case = false
+ij_sass_hex_color_short_format = false
+ij_sass_hex_color_upper_case = false
+ij_sass_keep_blank_lines_in_code = 2
+ij_sass_keep_indents_on_empty_lines = false
+ij_sass_keep_single_line_blocks = false
+ij_sass_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
+ij_sass_space_after_colon = true
+ij_sass_space_before_opening_brace = true
+ij_sass_value_alignment = 0
+
+[*.scss]
+indent_size = 2
+ij_scss_align_closing_brace_with_properties = false
+ij_scss_blank_lines_around_nested_selector = 1
+ij_scss_blank_lines_between_blocks = 1
+ij_scss_brace_placement = 0
+ij_scss_hex_color_long_format = false
+ij_scss_hex_color_lower_case = false
+ij_scss_hex_color_short_format = false
+ij_scss_hex_color_upper_case = false
+ij_scss_keep_blank_lines_in_code = 2
+ij_scss_keep_indents_on_empty_lines = false
+ij_scss_keep_single_line_blocks = false
+ij_scss_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
+ij_scss_space_after_colon = true
+ij_scss_space_before_opening_brace = true
+ij_scss_value_alignment = 0
+
+[*.twig]
+ij_twig_keep_indents_on_empty_lines = false
+ij_twig_spaces_inside_delimiters = true
+ij_twig_spaces_inside_variable_delimiters = true
+
+[.editorconfig]
+ij_editorconfig_align_group_field_declarations = false
+ij_editorconfig_space_after_colon = false
+ij_editorconfig_space_after_comma = true
+ij_editorconfig_space_before_colon = false
+ij_editorconfig_space_before_comma = false
+ij_editorconfig_spaces_around_assignment_operators = true
+
+[xdebug.yml]
+indent_size = 2
+tab_width = 2
+
+[{*.ats,*.ts}]
+ij_continuation_indent_size = 4
+ij_typescript_align_imports = false
+ij_typescript_align_multiline_array_initializer_expression = false
+ij_typescript_align_multiline_binary_operation = false
+ij_typescript_align_multiline_chained_methods = false
+ij_typescript_align_multiline_extends_list = false
+ij_typescript_align_multiline_for = true
+ij_typescript_align_multiline_parameters = true
+ij_typescript_align_multiline_parameters_in_calls = false
+ij_typescript_align_multiline_ternary_operation = false
+ij_typescript_align_object_properties = 0
+ij_typescript_align_union_types = false
+ij_typescript_align_var_statements = 0
+ij_typescript_array_initializer_new_line_after_left_brace = false
+ij_typescript_array_initializer_right_brace_on_new_line = false
+ij_typescript_array_initializer_wrap = off
+ij_typescript_assignment_wrap = off
+ij_typescript_binary_operation_sign_on_next_line = false
+ij_typescript_binary_operation_wrap = off
+ij_typescript_blacklist_imports = rxjs/Rx,node_modules/**/*
+ij_typescript_blank_lines_after_imports = 1
+ij_typescript_blank_lines_around_class = 1
+ij_typescript_blank_lines_around_field = 0
+ij_typescript_blank_lines_around_field_in_interface = 0
+ij_typescript_blank_lines_around_function = 1
+ij_typescript_blank_lines_around_method = 1
+ij_typescript_blank_lines_around_method_in_interface = 1
+ij_typescript_block_brace_style = end_of_line
+ij_typescript_call_parameters_new_line_after_left_paren = false
+ij_typescript_call_parameters_right_paren_on_new_line = false
+ij_typescript_call_parameters_wrap = off
+ij_typescript_catch_on_new_line = false
+ij_typescript_chained_call_dot_on_new_line = true
+ij_typescript_class_brace_style = end_of_line
+ij_typescript_comma_on_new_line = false
+ij_typescript_do_while_brace_force = never
+ij_typescript_else_on_new_line = false
+ij_typescript_enforce_trailing_comma = keep
+ij_typescript_extends_keyword_wrap = off
+ij_typescript_extends_list_wrap = off
+ij_typescript_field_prefix = _
+ij_typescript_file_name_style = relaxed
+ij_typescript_finally_on_new_line = false
+ij_typescript_for_brace_force = never
+ij_typescript_for_statement_new_line_after_left_paren = false
+ij_typescript_for_statement_right_paren_on_new_line = false
+ij_typescript_for_statement_wrap = off
+ij_typescript_force_quote_style = false
+ij_typescript_force_semicolon_style = false
+ij_typescript_function_expression_brace_style = end_of_line
+ij_typescript_if_brace_force = never
+ij_typescript_import_merge_members = global
+ij_typescript_import_prefer_absolute_path = global
+ij_typescript_import_sort_members = true
+ij_typescript_import_sort_module_name = false
+ij_typescript_import_use_node_resolution = true
+ij_typescript_imports_wrap = on_every_item
+ij_typescript_indent_case_from_switch = true
+ij_typescript_indent_chained_calls = true
+ij_typescript_indent_package_children = 0
+ij_typescript_jsdoc_include_types = false
+ij_typescript_jsx_attribute_value = braces
+ij_typescript_keep_blank_lines_in_code = 2
+ij_typescript_keep_first_column_comment = true
+ij_typescript_keep_indents_on_empty_lines = false
+ij_typescript_keep_line_breaks = true
+ij_typescript_keep_simple_blocks_in_one_line = false
+ij_typescript_keep_simple_methods_in_one_line = false
+ij_typescript_line_comment_add_space = true
+ij_typescript_line_comment_at_first_column = false
+ij_typescript_method_brace_style = end_of_line
+ij_typescript_method_call_chain_wrap = off
+ij_typescript_method_parameters_new_line_after_left_paren = false
+ij_typescript_method_parameters_right_paren_on_new_line = false
+ij_typescript_method_parameters_wrap = off
+ij_typescript_object_literal_wrap = on_every_item
+ij_typescript_parentheses_expression_new_line_after_left_paren = false
+ij_typescript_parentheses_expression_right_paren_on_new_line = false
+ij_typescript_place_assignment_sign_on_next_line = false
+ij_typescript_prefer_as_type_cast = false
+ij_typescript_prefer_parameters_wrap = false
+ij_typescript_reformat_c_style_comments = false
+ij_typescript_space_after_colon = true
+ij_typescript_space_after_comma = true
+ij_typescript_space_after_dots_in_rest_parameter = false
+ij_typescript_space_after_generator_mult = true
+ij_typescript_space_after_property_colon = true
+ij_typescript_space_after_quest = true
+ij_typescript_space_after_type_colon = true
+ij_typescript_space_after_unary_not = false
+ij_typescript_space_before_async_arrow_lparen = true
+ij_typescript_space_before_catch_keyword = true
+ij_typescript_space_before_catch_left_brace = true
+ij_typescript_space_before_catch_parentheses = true
+ij_typescript_space_before_class_lbrace = true
+ij_typescript_space_before_class_left_brace = true
+ij_typescript_space_before_colon = true
+ij_typescript_space_before_comma = false
+ij_typescript_space_before_do_left_brace = true
+ij_typescript_space_before_else_keyword = true
+ij_typescript_space_before_else_left_brace = true
+ij_typescript_space_before_finally_keyword = true
+ij_typescript_space_before_finally_left_brace = true
+ij_typescript_space_before_for_left_brace = true
+ij_typescript_space_before_for_parentheses = true
+ij_typescript_space_before_for_semicolon = false
+ij_typescript_space_before_function_left_parenth = true
+ij_typescript_space_before_generator_mult = false
+ij_typescript_space_before_if_left_brace = true
+ij_typescript_space_before_if_parentheses = true
+ij_typescript_space_before_method_call_parentheses = false
+ij_typescript_space_before_method_left_brace = true
+ij_typescript_space_before_method_parentheses = false
+ij_typescript_space_before_property_colon = false
+ij_typescript_space_before_quest = true
+ij_typescript_space_before_switch_left_brace = true
+ij_typescript_space_before_switch_parentheses = true
+ij_typescript_space_before_try_left_brace = true
+ij_typescript_space_before_type_colon = false
+ij_typescript_space_before_unary_not = false
+ij_typescript_space_before_while_keyword = true
+ij_typescript_space_before_while_left_brace = true
+ij_typescript_space_before_while_parentheses = true
+ij_typescript_spaces_around_additive_operators = true
+ij_typescript_spaces_around_arrow_function_operator = true
+ij_typescript_spaces_around_assignment_operators = true
+ij_typescript_spaces_around_bitwise_operators = true
+ij_typescript_spaces_around_equality_operators = true
+ij_typescript_spaces_around_logical_operators = true
+ij_typescript_spaces_around_multiplicative_operators = true
+ij_typescript_spaces_around_relational_operators = true
+ij_typescript_spaces_around_shift_operators = true
+ij_typescript_spaces_around_unary_operator = false
+ij_typescript_spaces_within_array_initializer_brackets = false
+ij_typescript_spaces_within_brackets = false
+ij_typescript_spaces_within_catch_parentheses = false
+ij_typescript_spaces_within_for_parentheses = false
+ij_typescript_spaces_within_if_parentheses = false
+ij_typescript_spaces_within_imports = false
+ij_typescript_spaces_within_interpolation_expressions = false
+ij_typescript_spaces_within_method_call_parentheses = false
+ij_typescript_spaces_within_method_parentheses = false
+ij_typescript_spaces_within_object_literal_braces = false
+ij_typescript_spaces_within_object_type_braces = true
+ij_typescript_spaces_within_parentheses = false
+ij_typescript_spaces_within_switch_parentheses = false
+ij_typescript_spaces_within_type_assertion = false
+ij_typescript_spaces_within_union_types = true
+ij_typescript_spaces_within_while_parentheses = false
+ij_typescript_special_else_if_treatment = true
+ij_typescript_ternary_operation_signs_on_next_line = false
+ij_typescript_ternary_operation_wrap = off
+ij_typescript_union_types_wrap = on_every_item
+ij_typescript_use_chained_calls_group_indents = false
+ij_typescript_use_double_quotes = true
+ij_typescript_use_explicit_js_extension = global
+ij_typescript_use_path_mapping = always
+ij_typescript_use_public_modifier = false
+ij_typescript_use_semicolon_after_statement = true
+ij_typescript_var_declaration_wrap = normal
+ij_typescript_while_brace_force = never
+ij_typescript_while_on_new_line = false
+ij_typescript_wrap_comments = false
+
+[{*.cjs,*.js}]
+ij_continuation_indent_size = 4
+ij_javascript_align_imports = false
+ij_javascript_align_multiline_array_initializer_expression = false
+ij_javascript_align_multiline_binary_operation = false
+ij_javascript_align_multiline_chained_methods = false
+ij_javascript_align_multiline_extends_list = false
+ij_javascript_align_multiline_for = true
+ij_javascript_align_multiline_parameters = true
+ij_javascript_align_multiline_parameters_in_calls = false
+ij_javascript_align_multiline_ternary_operation = false
+ij_javascript_align_object_properties = 0
+ij_javascript_align_union_types = false
+ij_javascript_align_var_statements = 0
+ij_javascript_array_initializer_new_line_after_left_brace = false
+ij_javascript_array_initializer_right_brace_on_new_line = false
+ij_javascript_array_initializer_wrap = off
+ij_javascript_assignment_wrap = off
+ij_javascript_binary_operation_sign_on_next_line = false
+ij_javascript_binary_operation_wrap = off
+ij_javascript_blacklist_imports = rxjs/Rx,node_modules/**/*
+ij_javascript_blank_lines_after_imports = 1
+ij_javascript_blank_lines_around_class = 1
+ij_javascript_blank_lines_around_field = 0
+ij_javascript_blank_lines_around_function = 1
+ij_javascript_blank_lines_around_method = 1
+ij_javascript_block_brace_style = end_of_line
+ij_javascript_call_parameters_new_line_after_left_paren = false
+ij_javascript_call_parameters_right_paren_on_new_line = false
+ij_javascript_call_parameters_wrap = off
+ij_javascript_catch_on_new_line = false
+ij_javascript_chained_call_dot_on_new_line = true
+ij_javascript_class_brace_style = end_of_line
+ij_javascript_comma_on_new_line = false
+ij_javascript_do_while_brace_force = never
+ij_javascript_else_on_new_line = false
+ij_javascript_enforce_trailing_comma = keep
+ij_javascript_extends_keyword_wrap = off
+ij_javascript_extends_list_wrap = off
+ij_javascript_field_prefix = _
+ij_javascript_file_name_style = relaxed
+ij_javascript_finally_on_new_line = false
+ij_javascript_for_brace_force = never
+ij_javascript_for_statement_new_line_after_left_paren = false
+ij_javascript_for_statement_right_paren_on_new_line = false
+ij_javascript_for_statement_wrap = off
+ij_javascript_force_quote_style = false
+ij_javascript_force_semicolon_style = false
+ij_javascript_function_expression_brace_style = end_of_line
+ij_javascript_if_brace_force = never
+ij_javascript_import_merge_members = global
+ij_javascript_import_prefer_absolute_path = global
+ij_javascript_import_sort_members = true
+ij_javascript_import_sort_module_name = false
+ij_javascript_import_use_node_resolution = true
+ij_javascript_imports_wrap = on_every_item
+ij_javascript_indent_case_from_switch = true
+ij_javascript_indent_chained_calls = true
+ij_javascript_indent_package_children = 0
+ij_javascript_jsx_attribute_value = braces
+ij_javascript_keep_blank_lines_in_code = 2
+ij_javascript_keep_first_column_comment = true
+ij_javascript_keep_indents_on_empty_lines = false
+ij_javascript_keep_line_breaks = true
+ij_javascript_keep_simple_blocks_in_one_line = false
+ij_javascript_keep_simple_methods_in_one_line = false
+ij_javascript_line_comment_add_space = true
+ij_javascript_line_comment_at_first_column = false
+ij_javascript_method_brace_style = end_of_line
+ij_javascript_method_call_chain_wrap = off
+ij_javascript_method_parameters_new_line_after_left_paren = false
+ij_javascript_method_parameters_right_paren_on_new_line = false
+ij_javascript_method_parameters_wrap = off
+ij_javascript_object_literal_wrap = on_every_item
+ij_javascript_parentheses_expression_new_line_after_left_paren = false
+ij_javascript_parentheses_expression_right_paren_on_new_line = false
+ij_javascript_place_assignment_sign_on_next_line = false
+ij_javascript_prefer_as_type_cast = false
+ij_javascript_prefer_parameters_wrap = false
+ij_javascript_reformat_c_style_comments = false
+ij_javascript_space_after_colon = true
+ij_javascript_space_after_comma = true
+ij_javascript_space_after_dots_in_rest_parameter = false
+ij_javascript_space_after_generator_mult = true
+ij_javascript_space_after_property_colon = true
+ij_javascript_space_after_quest = true
+ij_javascript_space_after_type_colon = true
+ij_javascript_space_after_unary_not = false
+ij_javascript_space_before_async_arrow_lparen = true
+ij_javascript_space_before_catch_keyword = true
+ij_javascript_space_before_catch_left_brace = true
+ij_javascript_space_before_catch_parentheses = true
+ij_javascript_space_before_class_lbrace = true
+ij_javascript_space_before_class_left_brace = true
+ij_javascript_space_before_colon = true
+ij_javascript_space_before_comma = false
+ij_javascript_space_before_do_left_brace = true
+ij_javascript_space_before_else_keyword = true
+ij_javascript_space_before_else_left_brace = true
+ij_javascript_space_before_finally_keyword = true
+ij_javascript_space_before_finally_left_brace = true
+ij_javascript_space_before_for_left_brace = true
+ij_javascript_space_before_for_parentheses = true
+ij_javascript_space_before_for_semicolon = false
+ij_javascript_space_before_function_left_parenth = true
+ij_javascript_space_before_generator_mult = false
+ij_javascript_space_before_if_left_brace = true
+ij_javascript_space_before_if_parentheses = true
+ij_javascript_space_before_method_call_parentheses = false
+ij_javascript_space_before_method_left_brace = true
+ij_javascript_space_before_method_parentheses = false
+ij_javascript_space_before_property_colon = false
+ij_javascript_space_before_quest = true
+ij_javascript_space_before_switch_left_brace = true
+ij_javascript_space_before_switch_parentheses = true
+ij_javascript_space_before_try_left_brace = true
+ij_javascript_space_before_type_colon = false
+ij_javascript_space_before_unary_not = false
+ij_javascript_space_before_while_keyword = true
+ij_javascript_space_before_while_left_brace = true
+ij_javascript_space_before_while_parentheses = true
+ij_javascript_spaces_around_additive_operators = true
+ij_javascript_spaces_around_arrow_function_operator = true
+ij_javascript_spaces_around_assignment_operators = true
+ij_javascript_spaces_around_bitwise_operators = true
+ij_javascript_spaces_around_equality_operators = true
+ij_javascript_spaces_around_logical_operators = true
+ij_javascript_spaces_around_multiplicative_operators = true
+ij_javascript_spaces_around_relational_operators = true
+ij_javascript_spaces_around_shift_operators = true
+ij_javascript_spaces_around_unary_operator = false
+ij_javascript_spaces_within_array_initializer_brackets = false
+ij_javascript_spaces_within_brackets = false
+ij_javascript_spaces_within_catch_parentheses = false
+ij_javascript_spaces_within_for_parentheses = false
+ij_javascript_spaces_within_if_parentheses = false
+ij_javascript_spaces_within_imports = false
+ij_javascript_spaces_within_interpolation_expressions = false
+ij_javascript_spaces_within_method_call_parentheses = false
+ij_javascript_spaces_within_method_parentheses = false
+ij_javascript_spaces_within_object_literal_braces = false
+ij_javascript_spaces_within_object_type_braces = true
+ij_javascript_spaces_within_parentheses = false
+ij_javascript_spaces_within_switch_parentheses = false
+ij_javascript_spaces_within_type_assertion = false
+ij_javascript_spaces_within_union_types = true
+ij_javascript_spaces_within_while_parentheses = false
+ij_javascript_special_else_if_treatment = true
+ij_javascript_ternary_operation_signs_on_next_line = false
+ij_javascript_ternary_operation_wrap = off
+ij_javascript_union_types_wrap = on_every_item
+ij_javascript_use_chained_calls_group_indents = false
+ij_javascript_use_double_quotes = true
+ij_javascript_use_explicit_js_extension = global
+ij_javascript_use_path_mapping = always
+ij_javascript_use_public_modifier = false
+ij_javascript_use_semicolon_after_statement = true
+ij_javascript_var_declaration_wrap = normal
+ij_javascript_while_brace_force = never
+ij_javascript_while_on_new_line = false
+ij_javascript_wrap_comments = false
+
+[{*.ctp,*.module,*.hphp,*.php,*.inc,*.phtml,*.php5,*.php4}]
+ij_continuation_indent_size = 4
+ij_php_align_assignments = false
+ij_php_align_class_constants = false
+ij_php_align_group_field_declarations = false
+ij_php_align_inline_comments = false
+ij_php_align_key_value_pairs = false
+ij_php_align_multiline_array_initializer_expression = false
+ij_php_align_multiline_binary_operation = false
+ij_php_align_multiline_chained_methods = false
+ij_php_align_multiline_extends_list = false
+ij_php_align_multiline_for = true
+ij_php_align_multiline_parameters = true
+ij_php_align_multiline_parameters_in_calls = false
+ij_php_align_multiline_ternary_operation = false
+ij_php_align_phpdoc_comments = false
+ij_php_align_phpdoc_param_names = false
+ij_php_api_weight = 28
+ij_php_array_initializer_new_line_after_left_brace = false
+ij_php_array_initializer_right_brace_on_new_line = false
+ij_php_array_initializer_wrap = off
+ij_php_assignment_wrap = off
+ij_php_author_weight = 28
+ij_php_binary_operation_sign_on_next_line = false
+ij_php_binary_operation_wrap = off
+ij_php_blank_lines_after_class_header = 0
+ij_php_blank_lines_after_function = 1
+ij_php_blank_lines_after_imports = 1
+ij_php_blank_lines_after_opening_tag = 0
+ij_php_blank_lines_after_package = 0
+ij_php_blank_lines_around_class = 1
+ij_php_blank_lines_around_constants = 0
+ij_php_blank_lines_around_field = 0
+ij_php_blank_lines_around_method = 1
+ij_php_blank_lines_before_class_end = 0
+ij_php_blank_lines_before_imports = 1
+ij_php_blank_lines_before_method_body = 0
+ij_php_blank_lines_before_package = 1
+ij_php_blank_lines_before_return_statement = 0
+ij_php_block_brace_style = end_of_line
+ij_php_call_parameters_new_line_after_left_paren = false
+ij_php_call_parameters_right_paren_on_new_line = false
+ij_php_call_parameters_wrap = off
+ij_php_catch_on_new_line = false
+ij_php_category_weight = 28
+ij_php_class_brace_style = next_line
+ij_php_comma_after_last_array_element = false
+ij_php_concat_spaces = true
+ij_php_copyright_weight = 28
+ij_php_deprecated_weight = 28
+ij_php_do_while_brace_force = never
+ij_php_else_if_style = as_is
+ij_php_else_on_new_line = false
+ij_php_example_weight = 28
+ij_php_extends_keyword_wrap = off
+ij_php_extends_list_wrap = off
+ij_php_fields_default_visibility = private
+ij_php_filesource_weight = 28
+ij_php_finally_on_new_line = false
+ij_php_for_brace_force = never
+ij_php_for_statement_new_line_after_left_paren = false
+ij_php_for_statement_right_paren_on_new_line = false
+ij_php_for_statement_wrap = off
+ij_php_force_short_declaration_array_style = false
+ij_php_global_weight = 28
+ij_php_group_use_wrap = on_every_item
+ij_php_if_brace_force = never
+ij_php_if_lparen_on_next_line = false
+ij_php_if_rparen_on_next_line = false
+ij_php_ignore_weight = 28
+ij_php_import_sorting = alphabetic
+ij_php_indent_break_from_case = true
+ij_php_indent_case_from_switch = true
+ij_php_indent_code_in_php_tags = false
+ij_php_internal_weight = 28
+ij_php_keep_blank_lines_after_lbrace = 2
+ij_php_keep_blank_lines_before_right_brace = 2
+ij_php_keep_blank_lines_in_code = 2
+ij_php_keep_blank_lines_in_declarations = 2
+ij_php_keep_control_statement_in_one_line = true
+ij_php_keep_first_column_comment = true
+ij_php_keep_indents_on_empty_lines = false
+ij_php_keep_line_breaks = true
+ij_php_keep_rparen_and_lbrace_on_one_line = true
+ij_php_keep_simple_methods_in_one_line = false
+ij_php_lambda_brace_style = end_of_line
+ij_php_license_weight = 28
+ij_php_line_comment_add_space = false
+ij_php_line_comment_at_first_column = true
+ij_php_link_weight = 28
+ij_php_lower_case_boolean_const = false
+ij_php_lower_case_null_const = false
+ij_php_method_brace_style = next_line
+ij_php_method_call_chain_wrap = off
+ij_php_method_parameters_new_line_after_left_paren = false
+ij_php_method_parameters_right_paren_on_new_line = false
+ij_php_method_parameters_wrap = off
+ij_php_method_weight = 28
+ij_php_modifier_list_wrap = false
+ij_php_multiline_chained_calls_semicolon_on_new_line = false
+ij_php_namespace_brace_style = 1
+ij_php_null_type_position = in_the_end
+ij_php_package_weight = 28
+ij_php_param_weight = 0
+ij_php_parentheses_expression_new_line_after_left_paren = false
+ij_php_parentheses_expression_right_paren_on_new_line = false
+ij_php_phpdoc_blank_line_before_tags = false
+ij_php_phpdoc_blank_lines_around_parameters = false
+ij_php_phpdoc_keep_blank_lines = true
+ij_php_phpdoc_param_spaces_between_name_and_description = 1
+ij_php_phpdoc_param_spaces_between_tag_and_type = 1
+ij_php_phpdoc_param_spaces_between_type_and_name = 1
+ij_php_phpdoc_use_fqcn = false
+ij_php_phpdoc_wrap_long_lines = false
+ij_php_place_assignment_sign_on_next_line = false
+ij_php_place_parens_for_constructor = 0
+ij_php_property_read_weight = 28
+ij_php_property_weight = 28
+ij_php_property_write_weight = 28
+ij_php_return_type_on_new_line = false
+ij_php_return_weight = 1
+ij_php_see_weight = 28
+ij_php_since_weight = 28
+ij_php_sort_phpdoc_elements = true
+ij_php_space_after_colon = true
+ij_php_space_after_colon_in_return_type = true
+ij_php_space_after_comma = true
+ij_php_space_after_for_semicolon = true
+ij_php_space_after_quest = true
+ij_php_space_after_type_cast = false
+ij_php_space_after_unary_not = false
+ij_php_space_before_array_initializer_left_brace = false
+ij_php_space_before_catch_keyword = true
+ij_php_space_before_catch_left_brace = true
+ij_php_space_before_catch_parentheses = true
+ij_php_space_before_class_left_brace = true
+ij_php_space_before_closure_left_parenthesis = true
+ij_php_space_before_colon = true
+ij_php_space_before_colon_in_return_type = false
+ij_php_space_before_comma = false
+ij_php_space_before_do_left_brace = true
+ij_php_space_before_else_keyword = true
+ij_php_space_before_else_left_brace = true
+ij_php_space_before_finally_keyword = true
+ij_php_space_before_finally_left_brace = true
+ij_php_space_before_for_left_brace = true
+ij_php_space_before_for_parentheses = true
+ij_php_space_before_for_semicolon = false
+ij_php_space_before_if_left_brace = true
+ij_php_space_before_if_parentheses = true
+ij_php_space_before_method_call_parentheses = false
+ij_php_space_before_method_left_brace = true
+ij_php_space_before_method_parentheses = false
+ij_php_space_before_quest = true
+ij_php_space_before_switch_left_brace = true
+ij_php_space_before_switch_parentheses = true
+ij_php_space_before_try_left_brace = true
+ij_php_space_before_unary_not = false
+ij_php_space_before_while_keyword = true
+ij_php_space_before_while_left_brace = true
+ij_php_space_before_while_parentheses = true
+ij_php_space_between_ternary_quest_and_colon = false
+ij_php_spaces_around_additive_operators = true
+ij_php_spaces_around_arrow = false
+ij_php_spaces_around_assignment_in_declare = false
+ij_php_spaces_around_assignment_operators = true
+ij_php_spaces_around_bitwise_operators = true
+ij_php_spaces_around_equality_operators = true
+ij_php_spaces_around_logical_operators = true
+ij_php_spaces_around_multiplicative_operators = true
+ij_php_spaces_around_null_coalesce_operator = true
+ij_php_spaces_around_relational_operators = true
+ij_php_spaces_around_shift_operators = true
+ij_php_spaces_around_unary_operator = false
+ij_php_spaces_around_var_within_brackets = false
+ij_php_spaces_within_array_initializer_braces = false
+ij_php_spaces_within_brackets = false
+ij_php_spaces_within_catch_parentheses = false
+ij_php_spaces_within_for_parentheses = false
+ij_php_spaces_within_if_parentheses = false
+ij_php_spaces_within_method_call_parentheses = false
+ij_php_spaces_within_method_parentheses = false
+ij_php_spaces_within_parentheses = false
+ij_php_spaces_within_short_echo_tags = true
+ij_php_spaces_within_switch_parentheses = false
+ij_php_spaces_within_while_parentheses = false
+ij_php_special_else_if_treatment = false
+ij_php_subpackage_weight = 28
+ij_php_ternary_operation_signs_on_next_line = false
+ij_php_ternary_operation_wrap = off
+ij_php_throws_weight = 2
+ij_php_todo_weight = 28
+ij_php_unknown_tag_weight = 28
+ij_php_upper_case_boolean_const = false
+ij_php_upper_case_null_const = false
+ij_php_uses_weight = 28
+ij_php_var_weight = 28
+ij_php_variable_naming_style = mixed
+ij_php_version_weight = 28
+ij_php_while_brace_force = never
+ij_php_while_on_new_line = false
+
+[{*.htm,*.shtml,*.sht,*.shtm,*.html}]
+ij_html_add_new_line_before_tags = body,div,p,form,h1,h2,h3
+ij_html_align_attributes = true
+ij_html_align_text = false
+ij_html_attribute_wrap = normal
+ij_html_block_comment_at_first_column = true
+ij_html_do_not_align_children_of_min_lines = 0
+ij_html_do_not_break_if_inline_tags = title,h1,h2,h3,h4,h5,h6,p
+ij_html_do_not_indent_children_of_tags = html,body,thead,tbody,tfoot
+ij_html_enforce_quotes = false
+ij_html_inline_tags = a,abbr,acronym,b,basefont,bdo,big,br,cite,cite,code,dfn,em,font,i,img,input,kbd,label,q,s,samp,select,small,span,strike,strong,sub,sup,textarea,tt,u,var
+ij_html_keep_blank_lines = 2
+ij_html_keep_indents_on_empty_lines = false
+ij_html_keep_line_breaks = true
+ij_html_keep_line_breaks_in_text = true
+ij_html_keep_whitespaces = false
+ij_html_keep_whitespaces_inside = span,pre,textarea
+ij_html_line_comment_at_first_column = true
+ij_html_new_line_after_last_attribute = never
+ij_html_new_line_before_first_attribute = never
+ij_html_quote_style = double
+ij_html_remove_new_line_before_tags = br
+ij_html_space_after_tag_name = false
+ij_html_space_around_equality_in_attribute = false
+ij_html_space_inside_empty_tag = false
+ij_html_text_wrap = normal
+
+[{*.yml,*.yaml}]
+indent_size = 2
+ij_continuation_indent_size = 2
+ij_yaml_keep_indents_on_empty_lines = false
+ij_yaml_keep_line_breaks = true
+
+[{composer.lock,.stylelintrc,.eslintrc,.babelrc,jest.config,*.json,*.bowerrc,*.jsb3,*.jsb2}]
+indent_size = 2
+ij_json_keep_blank_lines_in_code = 0
+ij_json_keep_indents_on_empty_lines = false
+ij_json_keep_line_breaks = true
+ij_json_space_after_colon = true
+ij_json_space_after_comma = true
+ij_json_space_before_colon = true
+ij_json_space_before_comma = false
+ij_json_spaces_within_braces = false
+ij_json_spaces_within_brackets = false
+ij_json_wrap_long_lines = false
+
+[{phpunit.xml.dist,*.tld,*.xslt,*.jhm,*.rng,*.ant,*.xul,*.xsl,*.xsd,*.jnlp,*.xml,*.jrxml,*.fxml,*.wsdl}]
+ij_xml_block_comment_at_first_column = true
+ij_xml_keep_indents_on_empty_lines = false
+ij_xml_line_comment_at_first_column = true
diff --git a/.travis.yml b/.travis.yml
index 6f92253..2f7d92f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,11 +1,10 @@
language: php
php:
- - 5.3
- - 5.4
+ - 7.2
before_script:
- - curl -s http://getcomposer.org/installer | php
- - php composer.phar install --dev
+ - curl -s http://getcomposer.org/installer | php
+ - php composer.phar install
-script: phpunit --coverage-text
+script: composer run tests
diff --git a/README.md b/README.md
index 77c5cfd..6f51503 100644
--- a/README.md
+++ b/README.md
@@ -48,8 +48,8 @@ add appropriate modules from the Linux Kernel:
For *LEDs*, enable the gpio module :
-``` bash
-$ sudo modprobe w1-gpio
+```bash
+sudo modprobe w1-gpio
```
([see a complete circuit diagram for a single LED + explanations & schemas here](https://projects.drogon.net/raspberry-pi/gpio-examples/tux-crossing/gpio-examples-1-a-single-led/))
@@ -57,15 +57,15 @@ $ sudo modprobe w1-gpio
For *sensors*, enable the appropriate sensor.
By example for a [DS18B20 1-Wire digital temperature sensor](http://learn.adafruit.com/adafruits-raspberry-pi-lesson-11-ds18b20-temperature-sensing/overview):
-``` bash
-$ sudo modprobe w1-therm
+```bash
+sudo modprobe w1-therm
```
([see the DS18B20 in action on a Raspberry Pi here](https://github.com/ronanguilloux/temperature-pi))
To load such kernel modules automatically at boot time, edit the `/etc/modules` file & add these two lines:
-```
+```text
w1-gpio
w1-therm
```
@@ -78,15 +78,15 @@ The recommended way to install php-gpio is through [composer](http://getcomposer
Just run these three commands to install it
-``` bash
-$ sudo apt-get install git
-$ wget http://getcomposer.org/composer.phar
-$ php composer.phar create-project --stability='dev' ronanguilloux/php-gpio intoYourPath
+```bash
+sudo apt-get install git
+wget http://getcomposer.org/composer.phar
+php composer.phar create-project --stability='dev' ronanguilloux/php-gpio intoYourPath
```
Now you can add the autoloader, and you will have access to the library:
-``` php
+```php
= (int)($argv[1]))
- || (0 >= (int)($argv[2]))
+ !(3 === $argc)
+ || (0 >= (int)($argv[1]))
+ || (0 >= (int)($argv[2]))
) {
echo $msg = "This script expect 2 positive integer arguments: please check the README file";
- throw new \Exception($msg);
+ throw new Exception($msg);
}
@@ -38,7 +38,7 @@ $pin = (int)$argv[1];
$sleeper = (int)$argv[2];
$gpio = new GPIO();
-if(!in_array($pin, $gpio->getHackablePins())){
+if (!in_array($pin, $gpio->getHackablePins())) {
echo $msg = "$pin is not a hackable gpio pin number";
throw new \InvalidArgumentException($msg);
}
diff --git a/composer.json b/composer.json
index df4a9a1..8a93c6e 100644
--- a/composer.json
+++ b/composer.json
@@ -1,25 +1,55 @@
{
- "name": "ronanguilloux/php-gpio",
- "type": "library",
- "description": "GPIO-related utils & toolkit PHP library",
- "keywords": ["GPIO", "hardware", "chipset", "input", "output", "port", "pin", "chip", "sensors", "raspberry", "raspberry pi"],
- "homepage": "https://github.com/ronanguilloux/php-gpio",
- "license": "MIT",
- "authors": [
- {
- "name": "Ronan Guilloux",
- "email": "ronan.guilloux@gmail.com"
- }
- ],
- "require": {
- "php": ">=5.3.0"
- },
- "autoload": {
- "psr-0": { "PhpGpio": "src/" }
- },
- "extra": {
- "branch-alias": {
- "dev-master": "1.0.x-dev"
- }
+ "name": "ronanguilloux/php-gpio",
+ "type": "library",
+ "description": "GPIO-related utils & toolkit PHP library",
+ "keywords": [
+ "GPIO",
+ "hardware",
+ "chipset",
+ "input",
+ "output",
+ "port",
+ "pin",
+ "chip",
+ "sensors",
+ "raspberry",
+ "raspberry pi"
+ ],
+ "homepage": "https://github.com/ronanguilloux/php-gpio",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Ronan Guilloux",
+ "email": "ronan.guilloux@gmail.com"
}
+ ],
+ "require": {
+ "php": ">=7.0.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7.0",
+ "phpstan/phpstan": "^0.11",
+ "squizlabs/php_codesniffer": "3.*"
+ },
+ "autoload": {
+ "psr-4": {
+ "PhpGpio\\": "src/PhpGpio/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "PhpGpio\\Test\\": "tests/"
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "scripts": {
+ "tests": "phpdbg -qrr vendor/bin/phpunit tests",
+ "phpcs": "phpcs -ns --report=full",
+ "phpcs-fix": "phpcbf src tests src",
+ "phpstan": "phpstan analyse -l 6 --no-progress -n --ansi ./src/"
+ }
}
diff --git a/phpcs.xml b/phpcs.xml
new file mode 100644
index 0000000..1d286aa
--- /dev/null
+++ b/phpcs.xml
@@ -0,0 +1,33 @@
+
+
+ Mehrkanal coding standard
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ src
+ tests
+ tests/integration/assets/*
+
diff --git a/phpstan.neon b/phpstan.neon
new file mode 100644
index 0000000..f797243
--- /dev/null
+++ b/phpstan.neon
@@ -0,0 +1,5 @@
+parameters:
+ universalObjectCratesClasses:
+ - Zend\Stdlib\Parameters
+ includes:
+ - vendor/jangregor/phpstan-prophecy/src/extension.neon
diff --git a/src/PhpGpio/FileGetContentsService.php b/src/PhpGpio/FileGetContentsService.php
new file mode 100644
index 0000000..d7a78a0
--- /dev/null
+++ b/src/PhpGpio/FileGetContentsService.php
@@ -0,0 +1,19 @@
+getVersion() < 4) {
- $this->pins = array(
+ $this->pins = [
0, 1, 4, 7, 8, 9,
10, 11, 14, 15, 17, 18,
21, 22, 23, 24, 25
- );
- $this->hackablePins = array(
+ ];
+ $this->hackablePins = [
4, 7, 8, 9,
10, 11, 17, 18,
21, 22, 23, 24, 25
- );
- } else if($raspi->getVersion() < 16) {
+ ];
+ } elseif ($raspi->getVersion() < 16) {
# new GPIO layout (REV2)
- $this->pins = array(
+ $this->pins = [
2, 3, 4, 7, 8, 9,
10, 11, 14, 15, 17, 18,
22, 23, 24, 25, 27
- );
- $this->hackablePins = array(
+ ];
+ $this->hackablePins = [
4, 7, 8, 9,
10, 11, 17, 18,
22, 23, 24, 25, 27
- );
+ ];
} else {
# new GPIO layout (B+)
- $this->pins = array(
+ $this->pins = [
2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13,
14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25,
26, 27
- );
- $this->hackablePins = array(
+ ];
+ $this->hackablePins = [
4, 5, 6,
12, 13, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27
- );
+ ];
}
}
+ // exported pins for when we unexport all
+
/**
* getHackablePins : the pins you can hack with.
* @link http://elinux.org/RPi_Low-level_peripherals
* @return integer[]
*/
- public function getHackablePins()
+ public function getHackablePins(): array
{
return $this->hackablePins;
}
- private $directions = array(
- GpioInterface::DIRECTION_IN,
- GpioInterface::DIRECTION_OUT,
- );
-
- private $outputs = array(
- GpioInterface::IO_VALUE_ON,
- GpioInterface::IO_VALUE_OFF,
- );
-
- // exported pins for when we unexport all
- private $exportedPins = array();
-
/**
* Setup pin, takes pin number and direction (in or out)
*
- * @param int $pinNo
- * @param string $direction
+ * @param int $pinNo
+ * @param string $direction
* @return mixed string GPIO value or boolean false
*/
- public function setup($pinNo, $direction)
+ public function setup(int $pinNo, string $direction)
{
- if (!$this->isValidPin($pinNo)) {
- return false;
- }
+ $this->isValidPinOrException($pinNo);
// if exported, unexport it first
if ($this->isExported($pinNo)) {
@@ -100,7 +99,7 @@ public function setup($pinNo, $direction)
// if valid direction then set direction
if ($this->isValidDirection($direction)) {
- file_put_contents(GpioInterface::PATH_GPIO.$pinNo.'/direction', $direction);
+ file_put_contents(GpioInterface::PATH_GPIO . $pinNo . '/direction', $direction);
}
// Add to exported pins array
@@ -110,67 +109,50 @@ public function setup($pinNo, $direction)
}
/**
- * Get input value
+ * Check for valid pin value
*
- * @param int $pinNo
- * @return false|string string GPIO value or boolean false
+ * @exception InvalidArgumentException
+ * @return boolean true
*/
- public function input($pinNo)
+ public function isValidPinOrException(int $pinNo)
{
- if (!$this->isValidPin($pinNo)) {
- return false;
+ if (!is_int($pinNo)) {
+ throw new InvalidArgumentException(sprintf('Pin number "%s" is invalid (integer expected).', $pinNo));
}
- if ($this->isExported($pinNo)) {
- if ($this->currentDirection($pinNo) != "out") {
- return trim(file_get_contents(GpioInterface::PATH_GPIO.$pinNo.'/value'));
- }
- throw new \Exception('Error!' . $this->currentDirection($pinNo) . ' is a wrong direction for this pin!');
+ if (!in_array($pinNo, $this->pins)) {
+ throw new InvalidArgumentException(sprintf('Pin number "%s" is invalid (out of exepected range).', $pinNo));
}
- return false;
+ return true;
}
/**
- * Set output value
+ * Check if pin is exported
*
- * @param int $pinNo
- * @param string $value
- * @return mixed Gpio current instance or boolean false
+ * @return boolean
*/
- public function output($pinNo, $value)
+ public function isExported(int $pinNo)
{
- if (!$this->isValidPin($pinNo)) {
- return false;
- }
- if (!$this->isValidOutput($value)) {
- return false;
- }
- if ($this->isExported($pinNo)) {
- if ($this->currentDirection($pinNo) != "in") {
- file_put_contents(GpioInterface::PATH_GPIO.$pinNo.'/value', $value);
- } else {
- throw new \Exception('Error! Wrong Direction for this pin! Meant to be out while it is ' . $this->currentDirection($pinNo));
- }
- }
+ $this->isValidPinOrException($pinNo);
- return $this;
+ return file_exists(GpioInterface::PATH_GPIO . $pinNo);
}
/**
* Unexport Pin
*
- * @param int $pinNo
+ * @param int $pinNo
* @return mixed Gpio current instance or boolean false
*/
- public function unexport($pinNo)
+ public function unexport(int $pinNo)
{
- if (!$this->isValidPin($pinNo)) {
- return false;
- }
+ $this->isValidPinOrException($pinNo);
if ($this->isExported($pinNo)) {
file_put_contents(GpioInterface::PATH_UNEXPORT, $pinNo);
foreach ($this->exportedPins as $key => $value) {
- if($value == $pinNo) unset($key);
+ if ($value == $pinNo) {
+ unset($key);
+ }
}
}
@@ -178,32 +160,50 @@ public function unexport($pinNo)
}
/**
- * Unexport all pins
+ * Check for valid direction, in or out
*
- * @return Gpio Gpio current instance or boolean false
+ * @exception InvalidArgumentException
*/
- public function unexportAll()
+ public function isValidDirection(string $direction)
{
- foreach ($this->exportedPins as $pinNo) {
- file_put_contents(GpioInterface::PATH_UNEXPORT, $pinNo);
+ if (!is_string($direction) || empty($direction)) {
+ throw new InvalidArgumentException(sprintf('Direction "%s" is invalid (string expected).', $direction));
+ }
+ if (!in_array($direction, $this->directions)) {
+ throw new InvalidArgumentException(sprintf('Direction "%s" is invalid (unknown direction).', $direction));
}
- $this->exportedPins = array();
-
- return $this;
}
/**
- * Check if pin is exported
+ * Get input value
*
- * @return boolean
+ * @param int $pinNo
+ * @return string GPIO value or boolean false
+ * @throws Exception
*/
- public function isExported($pinNo)
+ public function input(int $pinNo): string
{
- if (!$this->isValidPin($pinNo)) {
- return false;
+ $this->isValidPinOrException($pinNo);
+ if ($this->isExported($pinNo)) {
+ if ($this->currentDirection($pinNo) != "out") {
+ return trim(
+ FileGetContentsService::get(GpioInterface::PATH_GPIO . $pinNo . '/value')
+ );
+ }
+ throw new Exception('Error!' . $this->currentDirection($pinNo) . ' is a wrong direction for this pin!');
}
- return file_exists(GpioInterface::PATH_GPIO.$pinNo);
+ throw new Exception();
+ }
+
+ /**
+ * To Mock in Tests
+ *
+ * @param string $subpath
+ */
+ public function getGpioContent(string $subpath)
+ {
+ FileGetContentsService::get(GpioInterface::PATH_GPIO . $subpath);
}
/**
@@ -211,66 +211,62 @@ public function isExported($pinNo)
*
* @return false|string string pin's direction value or boolean false
*/
- public function currentDirection($pinNo)
+ public function currentDirection(int $pinNo)
{
- if (!$this->isValidPin($pinNo)) {
- return false;
- }
+ $this->isValidPinOrException($pinNo);
- return trim(file_get_contents(GpioInterface::PATH_GPIO.$pinNo.'/direction'));
+ return trim($this->getGpioContent($pinNo . '/direction'));
}
/**
- * Check for valid direction, in or out
+ * Set output value
*
- * @exception InvalidArgumentException
- * @return boolean true
+ * @param int $pinNo
+ * @param string $output
+ * @return GpioInterface current instance
+ * @throws Exception
*/
- public function isValidDirection($direction)
+ public function output(int $pinNo, string $output): GpioInterface
{
- if (!is_string($direction) || empty($direction)) {
- throw new \InvalidArgumentException(sprintf('Direction "%s" is invalid (string expected).', $direction));
- }
- if (!in_array($direction, $this->directions)) {
- throw new \InvalidArgumentException(sprintf('Direction "%s" is invalid (unknown direction).', $direction));
+ $this->isValidPinOrException($pinNo);
+ $this->isValidOutputOrException($output);
+
+ if ($this->isExported($pinNo)) {
+ if ($this->currentDirection($pinNo) != self::DIRECTION_IN) {
+ file_put_contents(GpioInterface::PATH_GPIO . $pinNo . '/value', $output);
+ } else {
+ throw new Exception('Error! Wrong Direction for this pin! Meant to be out while it is ' . $this->currentDirection($pinNo));
+ }
}
- return true;
+ return $this;
}
/**
* Check for valid output value
*
* @exception InvalidArgumentException
- * @return boolean true
+ * @param string $output
*/
- public function isValidOutput($output)
+ public function isValidOutputOrException(string $output)
{
- if (!is_int($output)) {
- throw new \InvalidArgumentException(sprintf('Pin value "%s" is invalid (integer expected).', $output));
- }
if (!in_array($output, $this->outputs)) {
- throw new \InvalidArgumentException(sprintf('Output value "%s" is invalid (out of exepected range).', $output));
+ throw new InvalidArgumentException(sprintf('Output value "%s" is invalid (out of exepected range).', $output));
}
-
- return true;
}
/**
- * Check for valid pin value
+ * Unexport all pins
*
- * @exception InvalidArgumentException
- * @return boolean true
+ * @return GpioInterface Gpio current instance or boolean false
*/
- public function isValidPin($pinNo)
+ public function unexportAll(): GpioInterface
{
- if (!is_int($pinNo)) {
- throw new \InvalidArgumentException(sprintf('Pin number "%s" is invalid (integer expected).', $pinNo));
- }
- if (!in_array($pinNo, $this->pins)) {
- throw new \InvalidArgumentException(sprintf('Pin number "%s" is invalid (out of exepected range).', $pinNo));
+ foreach ($this->exportedPins as $pinNo) {
+ file_put_contents(GpioInterface::PATH_UNEXPORT, $pinNo);
}
+ $this->exportedPins = [];
- return true;
+ return $this;
}
}
diff --git a/src/PhpGpio/GpioDevelop.php b/src/PhpGpio/GpioDevelop.php
index 6a70305..0fa591f 100644
--- a/src/PhpGpio/GpioDevelop.php
+++ b/src/PhpGpio/GpioDevelop.php
@@ -13,12 +13,12 @@ class GpioDevelop implements GpioInterface
/**
* @var array
*/
- public $pins = array(14, 15, 17, 18);
+ public $pins = [14, 15, 17, 18];
/**
* @var array
*/
- public $hackablePins = array(17, 18);
+ public $hackablePins = [17, 18];
/**
* @var int
@@ -36,7 +36,7 @@ class GpioDevelop implements GpioInterface
*
* @return array
*/
- public function getHackablePins()
+ public function getHackablePins(): array
{
return $this->hackablePins;
}
@@ -44,12 +44,12 @@ public function getHackablePins()
/**
* Setup pin, takes pin number and direction (in or out)
*
- * @param int $pinNo
- * @param string $direction
+ * @param int $pinNo
+ * @param string $direction
*
* @return GpioDevelop or boolean false
*/
- public function setup($pinNo, $direction)
+ public function setup(int $pinNo, string $direction)
{
return $this;
}
@@ -57,24 +57,24 @@ public function setup($pinNo, $direction)
/**
* Get input value
*
- * @param int $pinNo
+ * @param int $pinNo
*
- * @return int GPIO value or boolean false
+ * @return string GPIO value or boolean false
*/
- public function input($pinNo)
+ public function input(int $pinNo): string
{
- return $this->inputValue;
+ return (string)$this->inputValue;
}
/**
* Set output value
*
- * @param int $pinNo
- * @param string $value
+ * @param int $pinNo
+ * @param string $output
*
- * @return GpioDevelop or boolean false
+ * @return GpioInterface GpioDevelop
*/
- public function output($pinNo, $value)
+ public function output(int $pinNo, string $output): GpioInterface
{
return $this;
}
@@ -82,11 +82,11 @@ public function output($pinNo, $value)
/**
* Unexport Pin
*
- * @param int $pinNo
+ * @param int $pinNo
*
* @return GpioDevelop or boolean false
*/
- public function unexport($pinNo)
+ public function unexport(int $pinNo)
{
return $this;
}
@@ -94,9 +94,9 @@ public function unexport($pinNo)
/**
* Unexport all pins
*
- * @return GpioDevelop or boolean false
+ * @return GpioInterface
*/
- public function unexportAll()
+ public function unexportAll(): GpioInterface
{
return $this;
}
@@ -108,7 +108,7 @@ public function unexportAll()
*
* @return boolean
*/
- public function isExported($pinNo)
+ public function isExported(int $pinNo)
{
return in_array($pinNo, $this->pins) || in_array($pinNo, $this->hackablePins);
}
@@ -120,7 +120,7 @@ public function isExported($pinNo)
*
* @return string pin's direction value or boolean false
*/
- public function currentDirection($pinNo)
+ public function currentDirection(int $pinNo)
{
return $this->direction;
}
@@ -132,7 +132,7 @@ public function currentDirection($pinNo)
*
* @return boolean
*/
- public function isValidDirection($direction)
+ public function isValidDirection(string $direction)
{
return $direction == GpioInterface::DIRECTION_IN || $direction == GpioInterface::DIRECTION_OUT;
}
@@ -140,11 +140,11 @@ public function isValidDirection($direction)
/**
* Check for valid output value
*
- * @param mixed $output
+ * @param string $output
*
* @return boolean
*/
- public function isValidOutput($output)
+ public function isValidOutputOrException(string $output)
{
return $output == GpioInterface::IO_VALUE_ON || $output == GpioInterface::IO_VALUE_OFF;
}
@@ -156,7 +156,7 @@ public function isValidOutput($output)
*
* @return boolean
*/
- public function isValidPin($pinNo)
+ public function isValidPinOrException(int $pinNo)
{
return in_array($pinNo, $this->pins) || in_array($pinNo, $this->hackablePins);
}
diff --git a/src/PhpGpio/GpioInterface.php b/src/PhpGpio/GpioInterface.php
index 8f07f89..48b9607 100644
--- a/src/PhpGpio/GpioInterface.php
+++ b/src/PhpGpio/GpioInterface.php
@@ -25,52 +25,52 @@ interface GpioInterface
*
* @return array
*/
- public function getHackablePins();
+ public function getHackablePins(): array;
/**
* Setup pin, takes pin number and direction (in or out)
*
- * @param int $pinNo
- * @param string $direction
+ * @param int $pinNo
+ * @param string $direction
*
* @return GpioDevelop string GPIO value or boolean false
*/
- public function setup($pinNo, $direction);
+ public function setup(int $pinNo, string $direction);
/**
* Get input value
*
- * @param int $pinNo
+ * @param int $pinNo
*
- * @return integer string GPIO value or boolean false
+ * @return string GPIO value
*/
- public function input($pinNo);
+ public function input(int $pinNo): string;
/**
* Set output value
*
- * @param int $pinNo
- * @param string $value
+ * @param int $pinNo
+ * @param string $output
*
* @return GpioDevelop Gpio current instance or boolean false
*/
- public function output($pinNo, $value);
+ public function output(int $pinNo, string $output): GpioInterface;
/**
* Unexport Pin
*
- * @param int $pinNo
+ * @param int $pinNo
*
* @return GpioDevelop Gpio current instance or boolean false
*/
- public function unexport($pinNo);
+ public function unexport(int $pinNo);
/**
* Unexport all pins
*
- * @return GpioDevelop Gpio current instance or boolean false
+ * @return GpioInterface Gpio current instance
*/
- public function unexportAll();
+ public function unexportAll(): GpioInterface;
/**
* Check if pin is exported
@@ -79,7 +79,7 @@ public function unexportAll();
*
* @return boolean
*/
- public function isExported($pinNo);
+ public function isExported(int $pinNo);
/**
* get the pin's current direction
@@ -88,25 +88,23 @@ public function isExported($pinNo);
*
* @return string string pin's direction value or boolean false
*/
- public function currentDirection($pinNo);
+ public function currentDirection(int $pinNo);
/**
* Check for valid direction, in or out
*
* @param string $direction
- *
- * @return boolean
*/
- public function isValidDirection($direction);
+ public function isValidDirection(string $direction);
/**
* Check for valid output value
*
- * @param mixed $output
+ * @param string $output
*
* @return boolean
*/
- public function isValidOutput($output);
+ public function isValidOutputOrException(string $output);
/**
* Check for valid pin value
@@ -115,5 +113,5 @@ public function isValidOutput($output);
*
* @return boolean
*/
- public function isValidPin($pinNo);
+ public function isValidPinOrException(int $pinNo);
}
diff --git a/src/PhpGpio/Pi.php b/src/PhpGpio/Pi.php
index 413d1e6..cbe3e37 100644
--- a/src/PhpGpio/Pi.php
+++ b/src/PhpGpio/Pi.php
@@ -5,55 +5,60 @@
class Pi
{
/**
- *
* Get RaspberryPi version
- *
- * A list of Model and Pi Revision & Hardware Revision Code from '/proc/cpuinfo' is here:
+ *
+ * A list of Model and Pi Revision & Hardware Revision Code from '/proc/cpuinfo' is here:
* @link http://www.raspberrypi-spy.co.uk/2012/09/checking-your-raspberry-pi-board-version/
- *
- * @return decimal Raspi version
+ *
+ * @return int Raspi version
*/
- public function getVersion()
+ public function getVersion(): int
{
- $cpuinfo = preg_split ("/\n/", file_get_contents('/proc/cpuinfo'));
- foreach ($cpuinfo as $line) {
+ $result = FileGetContentsService::get('/proc/cpuinfo');
+ $cpuInfo = preg_split("/\n/", $result);
+
+ if (!is_array($cpuInfo)) {
+ return 0;
+ }
+
+ foreach ($cpuInfo as $line) {
if (preg_match('/Revision\s*:\s*([^\s]*)\s*/', $line, $matches)) {
- return hexdec($matches[1]);
+ return (int)hexdec($matches[1]);
}
}
return 0;
}
-
- public function getCpuLoad()
+
+ public function getCpuLoad(): array
{
return sys_getloadavg();
}
-
- public function getCpuTemp($fahrenheit = false)
+
+ public function getCpuTemp($fahrenheit = false): float
{
- $cputemp = floatval(file_get_contents('/sys/class/thermal/thermal_zone0/temp'))/1000;
-
- if($fahrenheit)
- $cputemp = 1.8* $cputemp+32;
-
+ $cputemp = floatval(file_get_contents('/sys/class/thermal/thermal_zone0/temp')) / 1000;
+
+ if ($fahrenheit) {
+ $cputemp = 1.8 * $cputemp + 32;
+ }
+
return $cputemp;
}
-
- public function getGpuTemp($fahrenheit = false)
+
+ public function getGpuTemp($fahrenheit = false): float
{
- $gputemp = floatval(str_replace(array('temp=', '\'C'), '', exec('/opt/vc/bin/vcgencmd measure_temp')));
-
- if($fahrenheit)
- $gputemp = 1.8* $gputemp+32;
+ $gputemp = floatval(str_replace(['temp=', '\'C'], '', exec('/opt/vc/bin/vcgencmd measure_temp')));
+
+ if ($fahrenheit) {
+ $gputemp = 1.8 * $gputemp + 32;
+ }
return $gputemp;
}
-
- public function getCpuFrequency()
+
+ public function getCpuFrequency(): float
{
- $frequency = floatval(file_get_contents('/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq'))/1000;
-
- return $frequency;
+ return floatval(file_get_contents('/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq')) / 1000;
}
}
diff --git a/src/PhpGpio/Sensors/DS18B20.php b/src/PhpGpio/Sensors/DS18B20.php
index 203906d..31563c4 100644
--- a/src/PhpGpio/Sensors/DS18B20.php
+++ b/src/PhpGpio/Sensors/DS18B20.php
@@ -10,48 +10,24 @@
* such as digital thermometers and weather instruments.
* (source : http://en.wikipedia.org/wiki/1-Wire)
*/
-class DS18B20 implements SensorInterface
-{
-
- private $bus = null; // ex: '/sys/bus/w1/devices/28-000003ced8f4/w1_slave'
- const BASEPATH = '/sys/bus/w1/devices/28-';
- /**
- * Get-Accesssor
- */
- public function getBus()
- {
- return $this->bus;
- }
+use Exception;
+use InvalidArgumentException;
+use PhpGpio\FileGetContentsService;
- /**
- * Set-Accesssor
- */
- public function setBus($value)
- {
- // ? is a non empty string, & a valid file path
- if (empty($value) || !is_string($value) || !file_exists($value)) {
- throw new \InvalidArgumentException("$value is not a valid w1 bus path");
- }
-
- // ? is a regular w1-bus path on a Raspbery ?
- if (!strstr($value, self::BASEPATH)) {
- throw new \InvalidArgumentException("$value does not seem to be a regular w1 bus path");
- }
+class DS18B20 implements SensorInterface
+{
+ const BASEPATH = '/sys/bus/w1/devices/28-'; // ex: '/sys/bus/w1/devices/28-000003ced8f4/w1_slave'
- $this->bus = $value;
- }
+ /** @var string */
+ protected $bus;
/**
* Setup
- *
- * @return $this
*/
public function __construct()
{
$this->bus = $this->guessBus();
-
- return $this;
}
/**
@@ -62,44 +38,56 @@ public function __construct()
*
* @return string $busPath
*/
- public function guessBus()
+ public function guessBus(): string
{
$busFolders = glob(self::BASEPATH . '*'); // predictable path on a Raspberry Pi
- if (0 === count($busFolders)) {
- return false;
+ if ($busFolders === false || 0 === count($busFolders)) {
+ throw new Exception('No bus found');
}
$busPath = $busFolders[0]; // get the first thermal sensor found
return $busPath . '/w1_slave';
}
+ public function getBus(): string
+ {
+ return $this->bus;
+ }
+
/**
- * Read
- *
- * @param array $args
- * @return float $value
+ * @param string $value
*/
- public function read($args = array())
+ public function setBus(string $value)
{
- if (!is_string($this->bus) || !file_exists($this->bus)) {
- throw new \Exception("No bus file found: please run sudo modprobe w1-gpio; sudo modprobe w1-therm & check the guessBus() method result");
+ // ? is a non empty string, & a valid file path
+ if (empty($value) || !is_string($value) || !file_exists($value)) {
+ throw new InvalidArgumentException("$value is not a valid w1 bus path");
}
- $raw = file_get_contents($this->bus);
- $raw = str_replace("\n", "", $raw);
- $boom = explode('t=',$raw);
- return floatval($boom[1]/1000);
+ // ? is a regular w1-bus path on a Raspbery ?
+ if (!strstr($value, self::BASEPATH)) {
+ throw new InvalidArgumentException("$value does not seem to be a regular w1 bus path");
+ }
+
+ $this->bus = $value;
}
/**
- * Write
+ * Read
*
* @param array $args
- * @return boolean
+ * @return float $value
+ * @throws Exception
*/
- public function write($args = array())
+ public function read($args = []): float
{
- return false;
- }
+ if (!is_string($this->bus) || !file_exists($this->bus)) {
+ throw new Exception("No bus file found: please run sudo modprobe w1-gpio; sudo modprobe w1-therm & check the guessBus() method result");
+ }
+ $raw = FileGetContentsService::get($this->bus);
+ $raw = str_replace("\n", '', $raw);
+ $boom = explode('t=', $raw);
+ return floatval($boom[1] / 1000);
+ }
}
diff --git a/src/PhpGpio/Sensors/MCP3002.php b/src/PhpGpio/Sensors/MCP3002.php
index e19bf0a..46f6c7e 100644
--- a/src/PhpGpio/Sensors/MCP3002.php
+++ b/src/PhpGpio/Sensors/MCP3002.php
@@ -2,18 +2,22 @@
namespace PhpGpio\Sensors;
+use InvalidArgumentException;
+use PhpGpio\Gpio;
+
/**
* The MCP3002 has a 10-bit analog to digital converter (ADC) with a simple to use SPI interface.
*
* @author
*/
-class MCP3002 implements SensorInterface {
+class MCP3002 implements SensorInterface
+{
private $_clockpin;
private $_mosipin;
private $_misopin;
private $_cspin;
-
+
private $_gpio;
/**
@@ -29,9 +33,10 @@ class MCP3002 implements SensorInterface {
* @param integer $misopin The Master In Slave Out (MISO) pin (ex. 9)
* @param integer $cspin The Chip Select (CSna) pin (ex. 8)
*/
- public function __construct($clockpin, $mosipin, $misopin, $cspin) {
- $this->_gpio = new GPIO();
-
+ public function __construct($clockpin, $mosipin, $misopin, $cspin)
+ {
+ $this->_gpio = new Gpio();
+
$this->_clockpin = $clockpin;
$this->_mosipin = $mosipin;
$this->_misopin = $misopin;
@@ -48,20 +53,22 @@ public function __construct($clockpin, $mosipin, $misopin, $cspin) {
* You should specify the channel (0|1) to read with the channel argument.
*
* @param array $args
- * @return integer
+ * @return float
+ * @throws \Exception
*/
- public function read($args = array()) {
+ public function read($args = []): float
+ {
$channel = $args['channel'];
- if (!is_integer($channel) || !in_array($channel, array(0, 1))) {
+ if (!is_integer($channel) || !in_array($channel, [0, 1])) {
echo $msg = "Only 2 channels are available on a Mcp3002: 0 or 1";
- throw new \InvalidArgumentException($msg);
+ throw new InvalidArgumentException($msg);
}
-
+
// init comm
$this->_gpio->output($this->_cspin, 1);
$this->_gpio->output($this->_clockpin, 0);
$this->_gpio->output($this->_cspin, 0);
-
+
// channel selection
$cmdout = (6 + $channel) << 5;
for ($i = 0; $i < 3; $i++) {
@@ -74,7 +81,7 @@ public function read($args = array()) {
$this->_gpio->output($this->_clockpin, 1);
$this->_gpio->output($this->_clockpin, 0);
}
-
+
$adcout = 0;
// read in one empty bit, one null bit and 10 ADC bits
for ($i = 0; $i < 12; $i++) {
@@ -85,12 +92,13 @@ public function read($args = array()) {
$adcout |= 0x1;
}
}
-
+
$this->_gpio->output($this->_cspin, 1);
return $adcout >> 1;
}
-
- public function write($args = array()) {
+
+ public function write($args = [])
+ {
return false;
}
}
diff --git a/src/PhpGpio/Sensors/SensorInterface.php b/src/PhpGpio/Sensors/SensorInterface.php
index 2d27e7b..4449c10 100644
--- a/src/PhpGpio/Sensors/SensorInterface.php
+++ b/src/PhpGpio/Sensors/SensorInterface.php
@@ -7,21 +7,11 @@
*/
interface SensorInterface
{
-
/**
* Read
*
* @param array $args
- * @return double
+ * @return float
*/
- public function read($args = array());
-
- /**
- * Write
- *
- * @param array $args
- * @return $this
- */
- public function write($args = array());
-
+ public function read($args = []): float;
}
diff --git a/tests/PhpGpio/Tests/GpioTest.php b/tests/PhpGpio/Tests/GpioTest.php
index 9e33b60..d504801 100755
--- a/tests/PhpGpio/Tests/GpioTest.php
+++ b/tests/PhpGpio/Tests/GpioTest.php
@@ -10,8 +10,8 @@
class GpioTest extends \PhpUnit_Framework_TestCase
{
private $gpio;
- private $rpi ='raspberrypi';
- private $hackablePins = array();
+ private $rpi = 'raspberrypi';
+ private $hackablePins = [];
public function setUp()
{
@@ -21,9 +21,9 @@ public function setUp()
// but in this test set, the Raspi is wired to a breadboard
// and the 4th Gpio pin is reserved to read the DS18B20 sensor.
// Other available gpio pins are connected to LEDs
- $this->hackablePins = array(
- 17, 18, 21, 22, 23,24, 25
- );
+ $this->hackablePins = [
+ 17, 18, 21, 22, 23, 24, 25
+ ];
}
/**
@@ -123,5 +123,4 @@ public function testSetupWithMissingArguments()
{
$this->gpio->setup(17);
}
-
}
diff --git a/tests/PhpGpio/Tests/PiTest.php b/tests/PhpGpio/Tests/PiTest.php
index 04e0c1f..fa85fd3 100755
--- a/tests/PhpGpio/Tests/PiTest.php
+++ b/tests/PhpGpio/Tests/PiTest.php
@@ -34,8 +34,7 @@ public function testGetVersion()
$this->assertPreconditionOrMarkTestSkipped();
$this->assertTrue($this->pi instanceof Pi);
$version = $this->pi->getVersion();
- $this->assertInternalType('integer' , $version);
-
+ $this->assertInternalType('integer', $version);
}
public function testGetCpuLoad()
@@ -45,7 +44,6 @@ public function testGetCpuLoad()
$result = $this->pi->getCpuLoad();
$this->assertTrue(is_array($result));
$this->assertCount(3, $result);
-
}
public function testGetCpuTemp()
@@ -53,8 +51,7 @@ public function testGetCpuTemp()
$this->assertPreconditionOrMarkTestSkipped();
$this->assertTrue($this->pi instanceof Pi);
$result = $this->pi->getCpuTemp();
- $this->assertInternalType('float' , $result);
-
+ $this->assertInternalType('float', $result);
}
public function testGetGpuTemp()
@@ -62,8 +59,7 @@ public function testGetGpuTemp()
$this->assertPreconditionOrMarkTestSkipped();
$this->assertTrue($this->pi instanceof Pi);
$result = $this->pi->getGpuTemp();
- $this->assertInternalType('float' , $result);
-
+ $this->assertInternalType('float', $result);
}
public function testGetCpuFrequence()
@@ -71,8 +67,6 @@ public function testGetCpuFrequence()
$this->assertPreconditionOrMarkTestSkipped();
$this->assertTrue($this->pi instanceof Pi);
$result = $this->pi->getCpuFrequency();
- $this->assertInternalType('float' , $result);
-
+ $this->assertInternalType('float', $result);
}
-
}
diff --git a/tests/PhpGpio/Tests/Sensors/DS18B20Test.php b/tests/PhpGpio/Tests/Sensors/DS18B20Test.php
index 5083df2..c6a3868 100755
--- a/tests/PhpGpio/Tests/Sensors/DS18B20Test.php
+++ b/tests/PhpGpio/Tests/Sensors/DS18B20Test.php
@@ -88,5 +88,4 @@ public function testRead()
$result = $this->sensor->read();
$this->assertTrue(is_float($result));
}
-
}
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index 4567666..8e8e5c6 100755
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -29,7 +29,7 @@
die(<<add('PhpGpio\Tests', __DIR__);