@@ -27,6 +27,10 @@ type Board struct {
2727 BoardID string
2828 Properties * properties.Map `json:"-"`
2929 PlatformRelease * PlatformRelease `json:"-"`
30+ configOptions * properties.Map
31+ configOptionValues map [string ]* properties.Map
32+ configOptionProperties map [string ]* properties.Map
33+ defaultConfig * properties.Map
3034 identificationProperties []* properties.Map
3135}
3236
@@ -64,66 +68,74 @@ func (b *Board) String() string {
6468 return b .FQBN ()
6569}
6670
71+ func (b * Board ) buildConfigOptionsStructures () {
72+ if b .configOptions != nil {
73+ return
74+ }
75+
76+ b .configOptions = properties .NewMap ()
77+ allConfigs := b .Properties .SubTree ("menu" )
78+ for _ , option := range allConfigs .FirstLevelKeys () {
79+ b .configOptions .Set (option , b .PlatformRelease .Menus .Get (option ))
80+ }
81+
82+ b .configOptionValues = map [string ]* properties.Map {}
83+ b .configOptionProperties = map [string ]* properties.Map {}
84+ b .defaultConfig = properties .NewMap ()
85+ for option , optionProps := range allConfigs .FirstLevelOf () {
86+ b .configOptionValues [option ] = properties .NewMap ()
87+ values := optionProps .FirstLevelKeys ()
88+ b .defaultConfig .Set (option , values [0 ])
89+ for _ , value := range values {
90+ if label , ok := optionProps .GetOk (value ); ok {
91+ b .configOptionValues [option ].Set (value , label )
92+ b .configOptionProperties [option + "=" + value ] = optionProps .SubTree (value )
93+ }
94+ }
95+ }
96+ }
97+
6798// GetConfigOptions returns an OrderedMap of configuration options for this board.
6899// The returned map will have key and value as option id and option name, respectively.
69100func (b * Board ) GetConfigOptions () * properties.Map {
70- res := properties .NewMap ()
71- menu := b .Properties .SubTree ("menu" )
72- for _ , option := range menu .FirstLevelKeys () {
73- res .Set (option , b .PlatformRelease .Menus .Get (option ))
74- }
75- return res
101+ b .buildConfigOptionsStructures ()
102+ return b .configOptions
76103}
77104
78105// GetConfigOptionValues returns an OrderedMap of possible values for a specific configuratio options
79106// for this board. The returned map will have key and value as option value and option value name,
80107// respectively.
81108func (b * Board ) GetConfigOptionValues (option string ) * properties.Map {
82- res := properties .NewMap ()
83- menu := b .Properties .SubTree ("menu" ).SubTree (option )
84- for _ , value := range menu .FirstLevelKeys () {
85- if label , ok := menu .GetOk (value ); ok {
86- res .Set (value , label )
87- }
88- }
89- return res
109+ b .buildConfigOptionsStructures ()
110+ return b .configOptionValues [option ]
90111}
91112
92113// GetBuildProperties returns the build properties and the build
93114// platform for the Board with the configuration passed as parameter.
94115func (b * Board ) GetBuildProperties (userConfigs * properties.Map ) (* properties.Map , error ) {
95- // Clone user configs because they are destroyed during iteration
96- userConfigs = userConfigs .Clone ()
116+ b .buildConfigOptionsStructures ()
117+
118+ // Override default configs with user configs
119+ config := b .defaultConfig .Clone ()
120+ config .Merge (userConfigs )
97121
98122 // Start with board's base properties
99123 buildProperties := b .Properties .Clone ()
100124
101125 // Add all sub-configurations one by one (a config is: option=value)
102- menu := b .Properties .SubTree ("menu" )
103- for _ , option := range menu .FirstLevelKeys () {
104- optionMenu := menu .SubTree (option )
105- userValue , haveUserValue := userConfigs .GetOk (option )
106- if haveUserValue {
107- userConfigs .Remove (option )
108- if ! optionMenu .ContainsKey (userValue ) {
109- return nil , fmt .Errorf (tr ("invalid value '%[1]s' for option '%[2]s'" ), userValue , option )
110- }
111- } else {
112- // apply default
113- userValue = optionMenu .FirstLevelKeys ()[0 ]
114- }
115-
116- optionsConf := optionMenu .SubTree (userValue )
117- buildProperties .Merge (optionsConf )
118- }
119-
120126 // Check for residual invalid options...
121- if invalidKeys := userConfigs .Keys (); len (invalidKeys ) > 0 {
122- invalidOption := invalidKeys [0 ]
123- if invalidOption == "" {
127+ for option , value := range config .AsMap () {
128+ if option == "" {
124129 return nil , fmt .Errorf (tr ("invalid empty option found" ))
125130 }
126- return nil , fmt .Errorf (tr ("invalid option '%s'" ), invalidOption )
131+ if _ , ok := b .configOptions .GetOk (option ); ! ok {
132+ return nil , fmt .Errorf (tr ("invalid option '%s'" ), option )
133+ }
134+ optionsConf , ok := b .configOptionProperties [option + "=" + value ]
135+ if ! ok {
136+ return nil , fmt .Errorf (tr ("invalid value '%[1]s' for option '%[2]s'" ), value , option )
137+ }
138+ buildProperties .Merge (optionsConf )
127139 }
128140
129141 return buildProperties , nil
@@ -153,7 +165,7 @@ func (b *Board) GetIdentificationProperties() []*properties.Map {
153165}
154166
155167// IsBoardMatchingIDProperties returns true if the board match the given
156- // identification properties
168+ // upload port identification properties
157169func (b * Board ) IsBoardMatchingIDProperties (query * properties.Map ) bool {
158170 // check checks if the given set of properties p match the "query"
159171 check := func (p * properties.Map ) bool {
@@ -179,3 +191,40 @@ func (b *Board) IsBoardMatchingIDProperties(query *properties.Map) bool {
179191func GetMonitorSettings (protocol string , boardProperties * properties.Map ) * properties.Map {
180192 return boardProperties .SubTree ("monitor_port." + protocol )
181193}
194+
195+ // IdentifyBoardConfiguration returns the configuration of the board that can be
196+ // deduced from the given upload port identification properties
197+ func (b * Board ) IdentifyBoardConfiguration (query * properties.Map ) * properties.Map {
198+ // check checks if the given set of properties p match the "query"
199+ check := func (p * properties.Map ) bool {
200+ for k , v := range p .AsMap () {
201+ if ! strings .EqualFold (query .Get (k ), v ) {
202+ return false
203+ }
204+ }
205+ return true
206+ }
207+ checkAll := func (allP []* properties.Map ) bool {
208+ for _ , p := range allP {
209+ if check (p ) {
210+ return true
211+ }
212+ }
213+ return false
214+ }
215+
216+ res := properties .NewMap ()
217+ for _ , option := range b .GetConfigOptions ().Keys () {
218+ values := b .GetConfigOptionValues (option ).Keys ()
219+
220+ for _ , value := range values {
221+ config := option + "=" + value
222+ configProps := b .configOptionProperties [config ]
223+
224+ if checkAll (configProps .ExtractSubIndexSets ("upload_port" )) {
225+ res .Set (option , value )
226+ }
227+ }
228+ }
229+ return res
230+ }
0 commit comments