xref: /aosp_15_r20/external/googleapis/google/maps/solar/v1/solar_service.proto (revision d5c09012810ac0c9f33fe448fb6da8260d444cc9)
1// Copyright 2023 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15syntax = "proto3";
16
17package google.maps.solar.v1;
18
19import "google/api/annotations.proto";
20import "google/api/client.proto";
21import "google/api/field_behavior.proto";
22import "google/api/httpbody.proto";
23import "google/type/date.proto";
24import "google/type/latlng.proto";
25import "google/type/money.proto";
26
27option csharp_namespace = "Google.Maps.Solar.V1";
28option go_package = "cloud.google.com/go/maps/solar/apiv1/solarpb;solarpb";
29option java_multiple_files = true;
30option java_outer_classname = "SolarServiceProto";
31option java_package = "com.google.maps.solar.v1";
32option objc_class_prefix = "GGMPV1A";
33option php_namespace = "Google\\Maps\\Solar\\V1";
34option ruby_package = "Google::Maps::Solar::V1";
35
36// Service definition for the Solar API.
37service Solar {
38  option (google.api.default_host) = "solar.googleapis.com";
39  option (google.api.oauth_scopes) =
40      "https://www.googleapis.com/auth/cloud-platform";
41
42  // Locates the closest building to a query point. Returns an error with
43  // code `NOT_FOUND` if there are no buildings within approximately 50m of the
44  // query point.
45  rpc FindClosestBuildingInsights(FindClosestBuildingInsightsRequest)
46      returns (BuildingInsights) {
47    option (google.api.http) = {
48      get: "/v1/buildingInsights:findClosest"
49    };
50  }
51
52  // Gets solar information for a region surrounding a location.
53  // Returns an error with code `NOT_FOUND` if the location is outside
54  // the coverage area.
55  rpc GetDataLayers(GetDataLayersRequest) returns (DataLayers) {
56    option (google.api.http) = {
57      get: "/v1/dataLayers:get"
58    };
59  }
60
61  // Returns an image by its ID.
62  rpc GetGeoTiff(GetGeoTiffRequest) returns (google.api.HttpBody) {
63    option (google.api.http) = {
64      get: "/v1/geoTiff:get"
65    };
66  }
67}
68
69// Request message for `Solar.FindClosestBuildingInsights`.
70message FindClosestBuildingInsightsRequest {
71  // Required. The longitude and latitude from which the API looks for the
72  // nearest known building.
73  google.type.LatLng location = 1 [(google.api.field_behavior) = REQUIRED];
74
75  // Optional. The minimum quality level allowed in the results. No result with
76  // lower quality than this will be returned. Not specifying this is
77  // equivalent to restricting to HIGH quality only.
78  ImageryQuality required_quality = 3 [(google.api.field_behavior) = OPTIONAL];
79
80  // Optional. Whether to require exact quality of the imagery.
81  // If set to false, the `required_quality` field is interpreted as the minimum
82  // required quality, such that HIGH quality imagery may be returned when
83  // `required_quality` is set to MEDIUM.  If set to true, `required_quality`
84  // is interpreted as the exact required quality and only `MEDIUM` quality
85  // imagery is returned if `required_quality` is set to `MEDIUM`.
86  bool exact_quality_required = 4 [(google.api.field_behavior) = OPTIONAL];
87}
88
89// A bounding box in lat/lng coordinates.
90message LatLngBox {
91  // The southwest corner of the box.
92  google.type.LatLng sw = 1;
93
94  // The northeast corner of the box.
95  google.type.LatLng ne = 2;
96}
97
98// Response message for `Solar.FindClosestBuildingInsights`.
99// Information about the location, dimensions, and solar potential of a
100// building.
101message BuildingInsights {
102  // The resource name for the building, of the format `building/<place ID>`.
103  string name = 1;
104
105  // A point near the center of the building.
106  google.type.LatLng center = 2;
107
108  // The bounding box of the building.
109  LatLngBox bounding_box = 9;
110
111  // Date that the underlying imagery was acquired. This is approximate.
112  google.type.Date imagery_date = 3;
113
114  // When processing was completed on this imagery.
115  google.type.Date imagery_processed_date = 11;
116
117  // Postal code (e.g., US zip code) this building is contained by.
118  string postal_code = 4;
119
120  // Administrative area 1 (e.g., in the US, the state) that contains this
121  // building. For example, in the US, the abbreviation might be "MA" or "CA."
122  string administrative_area = 5;
123
124  // Statistical area (e.g., US census tract) this building is in.
125  string statistical_area = 6;
126
127  // Region code for the country (or region) this building is in.
128  string region_code = 7;
129
130  // Solar potential of the building.
131  SolarPotential solar_potential = 8;
132
133  // The quality of the imagery used to compute the data for this building.
134  ImageryQuality imagery_quality = 10;
135}
136
137// Information about the solar potential of a building. A number of
138// fields in this are defined in terms of "panels". The fields
139// [panel_capacity_watts]
140// [google.maps.solar.v1.SolarPotential.panel_capacity_watts],
141// [panel_height_meters]
142// [google.maps.solar.v1.SolarPotential.panel_height_meters],
143// and [panel_width_meters]
144// [google.maps.solar.v1.SolarPotential.panel_width_meters]
145// describe the parameters of the model of panel used in these
146// calculations.
147message SolarPotential {
148  // Size of the maximum array - that is, the maximum number of panels that
149  // can fit on the roof.
150  int32 max_array_panels_count = 1;
151
152  // Capacity, in watts, of the panel used in the calculations.
153  float panel_capacity_watts = 9;
154
155  // Height, in meters in portrait orientation, of the panel used in
156  // the calculations.
157  float panel_height_meters = 10;
158
159  // Width, in meters in portrait orientation, of the panel used in
160  // the calculations.
161  float panel_width_meters = 11;
162
163  // The expected lifetime, in years, of the solar panels. This is
164  // used in the financial calculations.
165  int32 panel_lifetime_years = 12;
166
167  // Size, in square meters, of the maximum array.
168  float max_array_area_meters2 = 2;
169
170  // Maximum number of sunshine hours received per year, by any point
171  // on the roof. Sunshine hours are a measure of the total amount of
172  // insolation (energy) received per year. 1 sunshine hour = 1 kWh per kW
173  // (where kW refers to kW of capacity under Standard Testing Conditions).
174  float max_sunshine_hours_per_year = 3;
175
176  // Equivalent amount of CO2 produced per MWh of grid electricity. This
177  // is a measure of the carbon intensity of grid electricity displaced
178  // by solar electricity.
179  float carbon_offset_factor_kg_per_mwh = 4;
180
181  // Total size and sunlight quantiles for the part of the roof that
182  // was assigned to some roof segment. Despite the name, this may not
183  // include the entire building. See [building_stats]
184  // [google.maps.solar.v1.SolarPotential.building_stats].
185  SizeAndSunshineStats whole_roof_stats = 5;
186
187  // Size and sunlight quantiles for the entire building, including
188  // parts of the roof that were not assigned to some roof segment.
189  // Because the orientations of these parts are not well
190  // characterised, the roof area estimate is unreliable, but the
191  // ground area estimate is reliable. It may be that a more reliable
192  // whole building roof area can be obtained by scaling the roof area
193  // from [whole_roof_stats]
194  // [google.maps.solar.v1.SolarPotential.whole_roof_stats] by
195  // the ratio of the ground areas of `building_stats` and
196  // `whole_roof_stats`.
197  SizeAndSunshineStats building_stats = 13;
198
199  // Size and sunlight quantiles for each roof segment.
200  repeated RoofSegmentSizeAndSunshineStats roof_segment_stats = 6;
201
202  // Each [SolarPanel] [google.maps.solar.v1.SolarPanel]
203  // describes a single solar panel. They are listed in the order that
204  // the panel layout algorithm placed this. This is usually, though
205  // not always, in decreasing order of annual energy production.
206  repeated SolarPanel solar_panels = 14;
207
208  // Each [SolarPanelConfig]
209  // [google.maps.solar.v1.SolarPanelConfig] describes a
210  // different arrangement of solar panels on the roof. They are in
211  // order of increasing number of panels. The `SolarPanelConfig` with
212  // [panels_count]
213  // [google.maps.solar.v1.SolarPanelConfig.panels_count]=N is
214  // based on the first N panels in the `solar_panels` list. This field is only
215  // populated if at least 4 panels can fit on a roof.
216  repeated SolarPanelConfig solar_panel_configs = 7;
217
218  // A [FinancialAnalysis]
219  // [google.maps.solar.v1.FinancialAnalysis] gives the savings
220  // from going solar assuming a given monthly bill and a given
221  // electricity provider. They are in order of increasing order of
222  // monthly bill amount. This field will be empty for buildings in
223  // areas for which the Solar API does not have enough information to
224  // perform financial computations.
225  repeated FinancialAnalysis financial_analyses = 8;
226}
227
228// Information about the size and sunniness quantiles of a roof segment.
229message RoofSegmentSizeAndSunshineStats {
230  // Angle of the roof segment relative to the theoretical ground plane.
231  // 0 = parallel to the ground, 90 = perpendicular to the ground.
232  optional float pitch_degrees = 1;
233
234  // Compass direction the roof segment is pointing in. 0 = North, 90 =
235  // East, 180 = South. For a "flat" roof segment (`pitch_degrees` very
236  // near 0), azimuth is not well defined, so for consistency, we define it
237  // arbitrarily to be 0 (North).
238  optional float azimuth_degrees = 2;
239
240  // Total size and sunlight quantiles for the roof segment.
241  SizeAndSunshineStats stats = 3;
242
243  // A point near the center of the roof segment.
244  google.type.LatLng center = 4;
245
246  // The bounding box of the roof segment.
247  LatLngBox bounding_box = 5;
248
249  // The height of the roof segment plane, in meters above sea level,
250  // at the point designated by `center`. Together with the pitch,
251  // azimuth, and center location, this fully defines the roof segment
252  // plane.
253  optional float plane_height_at_center_meters = 6;
254}
255
256// Size and sunniness quantiles of a roof, or part of a roof.
257message SizeAndSunshineStats {
258  // The area of the roof or roof segment, in m^2. This is the roof area
259  // (accounting for tilt), not the ground footprint area.
260  float area_meters2 = 1;
261
262  // Quantiles of the pointwise sunniness across the area. If there
263  // are N values here, this represents the (N-1)-iles. For example,
264  // if there are 5 values, then they would be the quartiles (min,
265  // 25%, 50%, 75%, max). Values are in annual kWh/kW like
266  // [max_sunshine_hours_per_year]
267  // [google.maps.solar.v1.SolarPotential.max_sunshine_hours_per_year].
268  repeated float sunshine_quantiles = 2;
269
270  // The ground footprint area covered by the roof or roof segment, in m^2.
271  float ground_area_meters2 = 3;
272}
273
274// SolarPanel describes the position, orientation, and production of a
275// single solar panel. See the [panel_height_meters]
276// [google.maps.solar.v1.SolarPotential.panel_height_meters],
277// [panel_width_meters]
278// [google.maps.solar.v1.SolarPotential.panel_width_meters],
279// and [panel_capacity_watts]
280// [google.maps.solar.v1.SolarPotential.panel_capacity_watts]
281// fields in [SolarPotential]
282// [google.maps.solar.v1.SolarPotential] for information on the
283// parameters of the panel.
284message SolarPanel {
285  // The centre of the panel.
286  google.type.LatLng center = 1;
287
288  // The orientation of the panel.
289  SolarPanelOrientation orientation = 2;
290
291  // How much sunlight energy this layout captures over the course of a
292  // year, in DC kWh.
293  float yearly_energy_dc_kwh = 3;
294
295  // Index in [roof_segment_stats]
296  // [google.maps.solar.v1.SolarPotential.roof_segment_stats]
297  // of the `RoofSegmentSizeAndSunshineStats` which corresponds to the
298  // roof segment that this panel is placed on.
299  optional int32 segment_index = 4;
300}
301
302// SolarPanelConfig describes a particular placement of solar panels
303// on the roof.
304message SolarPanelConfig {
305  // Total number of panels. Note that this is redundant to (the sum
306  // of) the corresponding fields in [roof_segment_summaries]
307  // [google.maps.solar.v1.SolarPanelConfig.roof_segment_summaries].
308  int32 panels_count = 1;
309
310  // How much sunlight energy this layout captures over the course of a
311  // year, in DC kWh, assuming the panels described above.
312  float yearly_energy_dc_kwh = 2;
313
314  // Information about the production of each roof segment that is carrying
315  // at least one panel in this layout. `roof_segment_summaries[i]` describes
316  // the i-th roof segment, including its size, expected production and
317  // orientation.
318  repeated RoofSegmentSummary roof_segment_summaries = 4;
319}
320
321// Information about a roof segment on the building, with some number of
322// panels placed on it.
323message RoofSegmentSummary {
324  // Angle of the roof segment relative to the theoretical ground plane.
325  // 0 = parallel to the ground, 90 = perpendicular to the ground.
326  optional float pitch_degrees = 2;
327
328  // Compass direction the roof segment is pointing in. 0 = North, 90 =
329  // East, 180 = South. For a "flat" roof segment (`pitch_degrees` very
330  // near 0), azimuth is not well defined, so for consistency, we define it
331  // arbitrarily to be 0 (North).
332  optional float azimuth_degrees = 3;
333
334  // The total number of panels on this segment.
335  int32 panels_count = 7;
336
337  // How much sunlight energy this part of the layout captures over the
338  // course of a year, in DC kWh, assuming the panels described above.
339  float yearly_energy_dc_kwh = 8;
340
341  // Index in [roof_segment_stats]
342  // [google.maps.solar.v1.SolarPotential.roof_segment_stats]
343  // of the corresponding `RoofSegmentSizeAndSunshineStats`.
344  optional int32 segment_index = 9;
345}
346
347// Analysis of the cost and benefits of the optimum solar layout for a
348// particular electric bill size.
349message FinancialAnalysis {
350  // The monthly electric bill this analysis assumes.
351  google.type.Money monthly_bill = 3;
352
353  // Whether this is the bill size selected to be the default bill for the
354  // area this building is in. Exactly one `FinancialAnalysis` in
355  // `BuildingSolarPotential` should have `default_bill` set.
356  bool default_bill = 4;
357
358  // How much electricity the house uses in an average month, based on the
359  // bill size and the local electricity rates.
360  float average_kwh_per_month = 5;
361
362  // Index in [solar_panel_configs]
363  // [google.maps.solar.v1.SolarPotential.solar_panel_configs]
364  // of the optimum solar layout for this bill size. This can be -1
365  // indicating that there is no layout. In this case, the remaining
366  // submessages will be omitted.
367  optional int32 panel_config_index = 6;
368
369  // Financial information that applies regardless of the financing method
370  // used.
371  FinancialDetails financial_details = 7;
372
373  // Cost and benefit of leasing the solar panels.
374  LeasingSavings leasing_savings = 8;
375
376  // Cost and benefit of buying the solar panels with cash.
377  CashPurchaseSavings cash_purchase_savings = 9;
378
379  // Cost and benefit of buying the solar panels by financing the purchase.
380  FinancedPurchaseSavings financed_purchase_savings = 10;
381}
382
383// Details of a financial analysis. Some of these details are already
384// stored at higher levels (e.g., out of pocket cost). Total money
385// amounts are over a lifetime period defined by the
386// [panel_lifetime_years]
387// [google.maps.solar.v1.SolarPotential.panel_lifetime_years]
388// field in [SolarPotential]
389// [google.maps.solar.v1.SolarPotential]. Note: The out of
390// pocket cost of purchasing the panels is given in the
391// [out_of_pocket_cost]
392// [google.maps.solar.v1.CashPurchaseSavings.out_of_pocket_cost]
393// field in [CashPurchaseSavings]
394// [google.maps.solar.v1.CashPurchaseSavings].
395message FinancialDetails {
396  // How many AC kWh we think the solar panels will generate in their first
397  // year.
398  float initial_ac_kwh_per_year = 1;
399
400  // Utility bill for electricity not produced by solar, for the
401  // lifetime of the panels.
402  google.type.Money remaining_lifetime_utility_bill = 2;
403
404  // Amount of money available from federal incentives; this applies if the
405  // user buys (with or without a loan) the panels.
406  google.type.Money federal_incentive = 3;
407
408  // Amount of money available from state incentives; this applies if the
409  // user buys (with or without a loan) the panels.
410  google.type.Money state_incentive = 4;
411
412  // Amount of money available from utility incentives; this applies if the
413  // user buys (with or without a loan) the panels.
414  google.type.Money utility_incentive = 5;
415
416  // Amount of money the user will receive from Solar Renewable Energy
417  // Credits over the panel lifetime; this applies if the user buys
418  // (with or without a loan) the panels.
419  google.type.Money lifetime_srec_total = 6;
420
421  // Total cost of electricity the user would have paid over the
422  // lifetime period if they didn't install solar.
423  google.type.Money cost_of_electricity_without_solar = 7;
424
425  // Whether net metering is allowed.
426  bool net_metering_allowed = 8;
427
428  // Percentage (0-100) of the user's power supplied by solar.
429  // Valid for the first year but approximately correct for future years.
430  optional float solar_percentage = 9;
431
432  // The percentage (0-100) of solar electricity production we assumed was
433  // exported to the grid, based on the first quarter of production. This
434  // affects the calculations if net metering is not allowed.
435  optional float percentage_exported_to_grid = 10;
436}
437
438// Financial information that's shared between different financing methods.
439message SavingsOverTime {
440  // Savings in the first year after panel installation.
441  google.type.Money savings_year1 = 1;
442
443  // Savings in the first twenty years after panel installation.
444  google.type.Money savings_year20 = 2;
445
446  // Using the assumed discount rate, what is the present value of the
447  // cumulative 20-year savings?
448  google.type.Money present_value_of_savings_year20 = 3;
449
450  // Savings in the entire panel lifetime.
451  google.type.Money savings_lifetime = 5;
452
453  // Using the assumed discount rate, what is the present value of the
454  // cumulative lifetime savings?
455  google.type.Money present_value_of_savings_lifetime = 6;
456
457  // Indicates whether this scenario is financially viable.  Will be false for
458  // scenarios with poor financial viability (e.g., money-losing).
459  bool financially_viable = 4;
460}
461
462// Cost and benefit of leasing a particular configuration of solar panels
463// with a particular electricity usage.
464message LeasingSavings {
465  // Whether leases are allowed in this juristiction (leases are not
466  // allowed in some states). If this field is false, then the values in
467  // this message should probably be ignored.
468  bool leases_allowed = 1;
469
470  // Whether leases are supported in this juristiction by the financial
471  // calculation engine. If this field is false, then the values in this
472  // message should probably be ignored. This is independent of
473  // `leases_allowed`: in some areas leases are allowed, but under conditions
474  // that aren't handled by the financial models.
475  bool leases_supported = 2;
476
477  // Estimated annual leasing cost.
478  google.type.Money annual_leasing_cost = 3;
479
480  // How much is saved (or not) over the lifetime period.
481  SavingsOverTime savings = 4;
482}
483
484// Cost and benefit of an outright purchase of a particular configuration
485// of solar panels with a particular electricity usage.
486message CashPurchaseSavings {
487  // Initial cost before tax incentives: the amount that must be paid
488  // out-of-pocket. Contrast with `upfront_cost`, which is after tax incentives.
489  google.type.Money out_of_pocket_cost = 1;
490
491  // Initial cost after tax incentives: it's the amount that must be paid
492  // during first year. Contrast with `out_of_pocket_cost`, which is before tax
493  // incentives.
494  google.type.Money upfront_cost = 2;
495
496  // The value of all tax rebates.
497  google.type.Money rebate_value = 3;
498
499  // Number of years until payback occurs. A negative value means payback
500  // never occurs within the lifetime period.
501  optional float payback_years = 4;
502
503  // How much is saved (or not) over the lifetime period.
504  SavingsOverTime savings = 5;
505}
506
507// Cost and benefit of using a loan to buy a particular configuration
508// of solar panels with a particular electricity usage.
509message FinancedPurchaseSavings {
510  // Annual loan payments.
511  google.type.Money annual_loan_payment = 1;
512
513  // The value of all tax rebates (including Federal Investment Tax Credit
514  // (ITC)).
515  google.type.Money rebate_value = 2;
516
517  // The interest rate on loans assumed in this set of calculations.
518  float loan_interest_rate = 3;
519
520  // How much is saved (or not) over the lifetime period.
521  SavingsOverTime savings = 4;
522}
523
524// Request message for `Solar.GetDataLayers`.
525message GetDataLayersRequest {
526  // Required. The longitude and latitude for the center of the region to get
527  // data for.
528  google.type.LatLng location = 1 [(google.api.field_behavior) = REQUIRED];
529
530  // Required. The radius, in meters, defining the region surrounding that
531  // centre point for which data should be returned. The limitations
532  // on this value are:
533  //
534  // * Any value up to 100m can always be specified.
535  // * Values over 100m can be specified, as long as
536  //   `radius_meters` <= `pixel_size_meters * 1000`.
537  // * However, for values over 175m, the `DataLayerView` in the
538  //   request must not include monthly flux or hourly shade.
539  float radius_meters = 2 [(google.api.field_behavior) = REQUIRED];
540
541  // Optional. The desired subset of the data to return.
542  DataLayerView view = 3 [(google.api.field_behavior) = OPTIONAL];
543
544  // Optional. The minimum quality level allowed in the results. No result with
545  // lower quality than this will be returned. Not specifying this is
546  // equivalent to restricting to HIGH quality only.
547  ImageryQuality required_quality = 5 [(google.api.field_behavior) = OPTIONAL];
548
549  // Optional. The minimum scale, in meters per pixel, of the data to return.
550  // Values of 0.1 (the default, if this field is not set explicitly),
551  // 0.25, 0.5, and 1.0 are supported. Imagery components whose normal
552  // resolution is less than `pixel_size_meters` will be returned at
553  // the resolution specified by `pixel_size_meters`; imagery
554  // components whose normal resolution is equal to or greater than
555  // `pixel_size_meters` will be returned at that normal resolution.
556  float pixel_size_meters = 6 [(google.api.field_behavior) = OPTIONAL];
557
558  // Optional. Whether to require exact quality of the imagery.
559  // If set to false, the `required_quality` field is interpreted as the minimum
560  // required quality, such that HIGH quality imagery may be returned when
561  // `required_quality` is set to MEDIUM.  If set to true, `required_quality`
562  // is interpreted as the exact required quality and only `MEDIUM` quality
563  // imagery is returned if `required_quality` is set to `MEDIUM`.
564  bool exact_quality_required = 7 [(google.api.field_behavior) = OPTIONAL];
565}
566
567// Information about the solar potential of a region. The actual data
568// are contained in a number of GeoTIFF files covering the requested
569// region, for which this message contains URLs: Each string in the
570// `DataLayers` message contains a URL from which the
571// corresponding GeoTIFF can be fetched. These URLs are valid for a
572// few hours after they've been generated. Most of the GeoTIFF files
573// are at a resolution of 0.1m/pixel, but the monthly flux file is at
574// 0.5m/pixel, and the hourly shade files are at 1m/pixel. If a
575// `pixel_size_meters` value was specified in the
576// `GetDataLayersRequest`, then the minimum resolution in the GeoTIFF
577// files will be that value.
578message DataLayers {
579  // When the source imagery (from which all the other data are derived) in this
580  // region was taken. It is necessarily somewhat approximate, as the images may
581  // have been taken over more than one day.
582  google.type.Date imagery_date = 1;
583
584  // When processing was completed on this imagery.
585  google.type.Date imagery_processed_date = 2;
586
587  // The URL for an image of the DSM (Digital Surface Model) of the region.
588  // Values are in meters above EGM96 geoid (i.e., sea level). Invalid locations
589  // (where we don't have data) are stored as -9999.
590  string dsm_url = 3;
591
592  // The URL for an image of RGB data (aerial photo) of the region.
593  string rgb_url = 4;
594
595  // The URL for the building mask image: one bit per pixel saying whether that
596  // pixel is considered to be part of a rooftop or not.
597  string mask_url = 5;
598
599  // The URL for the annual flux map (annual sunlight on roofs) of the region.
600  // Values are kWh/kW/year. This is *unmasked flux*: flux is computed for every
601  // location, not just building rooftops. Invalid locations are stored as
602  // -9999: locations outside our coverage area will be invalid, and a few
603  // locations inside the coverage area, where we were unable to calculate flux,
604  // will also be invalid.
605  string annual_flux_url = 6;
606
607  // The URL for the monthly flux map (sunlight on roofs, broken down by month)
608  // of the region. Values are kWh/kW/year. The GeoTIFF pointed to by this URL
609  // will contain twelve bands, corresponding to January...December, in order.
610  string monthly_flux_url = 7;
611
612  // Twelve URLs for hourly shade, corresponding to January...December, in
613  // order. Each GeoTIFF will contain 24 bands, corresponding to the 24 hours of
614  // the day. Each pixel is a 32 bit integer, corresponding to the (up to) 31
615  // days of that month; a 1 bit means that the corresponding location is able
616  // to see the sun at that day, of that hour, of that month. Invalid locations
617  // are stored as -9999 (since this is negative, it has bit 31 set, and no
618  // valid value could have bit 31 set as that would correspond to the 32nd day
619  // of the month).
620  //
621  // An example may be useful. If you want to know whether a point (at
622  // pixel location (x, y)) saw sun at 4pm on the 22nd of June you
623  // would:
624  //
625  // 1. fetch the sixth URL in this list (corresponding to June).
626  // 1. look up the 17th channel (corresponding to 4pm).
627  // 1. read the 32-bit value at (x, y).
628  // 1. read bit 21 of the value (corresponding to the 22nd of the month).
629  // 1. if that bit is a 1, then that spot saw the sun at 4pm 22 June.
630  //
631  // More formally:
632  // Given `month` (1-12), `day` (1...month max; February has 28 days)
633  // and `hour` (0-23), the shade/sun for that month/day/hour at a
634  // position `(x, y)` is the bit
635  // ```
636  // (hourly_shade[month - 1])(x, y)[hour] & (1 << (day - 1))
637  // ```
638  // where `(x, y)` is spatial indexing, `[month - 1]` refers to
639  // fetching the `month - 1`st URL (indexing from zero), `[hour]` is
640  // indexing into the channels, and a final non-zero result means
641  // "sunny". There are no leap days, and DST doesn't exist (all days
642  // are 24 hours long; noon is always "standard time" noon).
643  repeated string hourly_shade_urls = 8;
644
645  // The quality of the result's imagery.
646  ImageryQuality imagery_quality = 9;
647}
648
649// Request message for `Solar.GetGeoTiff`.
650message GetGeoTiffRequest {
651  // Required. The ID of the asset being requested.
652  string id = 1 [(google.api.field_behavior) = REQUIRED];
653}
654
655// What subset of the solar information to return.
656enum DataLayerView {
657  // Equivalent to FULL.
658  DATA_LAYER_VIEW_UNSPECIFIED = 0;
659
660  // Get the DSM only.
661  DSM_LAYER = 1;
662
663  // Get the DSM, RGB, and mask.
664  IMAGERY_LAYERS = 2;
665
666  // Get the DSM, RGB, mask, and annual flux.
667  IMAGERY_AND_ANNUAL_FLUX_LAYERS = 3;
668
669  // Get the DSM, RGB, mask, annual flux, and monthly flux.
670  IMAGERY_AND_ALL_FLUX_LAYERS = 4;
671
672  // Get all data.
673  FULL_LAYERS = 5;
674}
675
676// The quality of the imagery used to compute some API result.
677//
678// Note: Regardless of imagery quality level, DSM outputs always have a
679// resolution of 0.1 m/pixel, monthly flux outputs always have a resolution of
680// 0.5 m/pixel, and hourly shade outputs always have a resolution of 1 m/pixel.
681enum ImageryQuality {
682  // No quality is known.
683  IMAGERY_QUALITY_UNSPECIFIED = 0;
684
685  // The underlying imagery and DSM data were processed at 0.1 m/pixel.
686  HIGH = 1;
687
688  // The underlying imagery and DSM data were processed at 0.25 m/pixel.
689  MEDIUM = 2;
690
691  // The underlying imagery and DSM data were processed at 0.5 m/pixel.
692  LOW = 3;
693}
694
695// The orientation of a solar panel. This must be interpreted relative to the
696// azimuth of the roof segment that the panel is placed on.
697enum SolarPanelOrientation {
698  // No panel orientation is known.
699  SOLAR_PANEL_ORIENTATION_UNSPECIFIED = 0;
700
701  // A `LANDSCAPE` panel has its long edge perpendicular to the
702  // azimuth direction of the roof segment that it is placed on.
703  LANDSCAPE = 1;
704
705  // A `PORTRAIT` panel has its long edge parallel to the azimuth
706  // direction of the roof segment that it is placed on.
707  PORTRAIT = 2;
708}
709